From e87a779adc8fcf8cfdbef4ce7ab31553a8dd1677 Mon Sep 17 00:00:00 2001 From: hstyi Date: Mon, 27 Oct 2025 17:34:37 +0800 Subject: [PATCH] chore: refactor Mixpanel integration and add event tracking --- .../kotlin/app/termora/ApplicationRunner.kt | 59 +------------ .../kotlin/app/termora/MixpanelService.kt | 85 +++++++++++++++++++ .../plugin/internal/plugin/PluginPanel.kt | 14 +++ 3 files changed, 100 insertions(+), 58 deletions(-) create mode 100644 src/main/kotlin/app/termora/MixpanelService.kt diff --git a/src/main/kotlin/app/termora/ApplicationRunner.kt b/src/main/kotlin/app/termora/ApplicationRunner.kt index c7a639b..6a4dac1 100644 --- a/src/main/kotlin/app/termora/ApplicationRunner.kt +++ b/src/main/kotlin/app/termora/ApplicationRunner.kt @@ -10,15 +10,11 @@ import com.formdev.flatlaf.extras.FlatInspector import com.formdev.flatlaf.ui.FlatTableCellBorder import com.formdev.flatlaf.util.SystemInfo import com.jthemedetecor.OsThemeDetector -import com.mixpanel.mixpanelapi.ClientDelivery -import com.mixpanel.mixpanelapi.MessageBuilder -import com.mixpanel.mixpanelapi.MixpanelAPI import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.apache.commons.io.FileUtils import org.apache.commons.lang3.LocaleUtils import org.apache.commons.lang3.SystemUtils -import org.json.JSONObject import org.slf4j.LoggerFactory import java.awt.* import java.awt.desktop.AppReopenedEvent @@ -369,61 +365,8 @@ class ApplicationRunner { if (Application.isUnknownVersion()) { return } - - swingCoroutineScope.launch(Dispatchers.IO) { - try { - val properties = JSONObject() - properties.put("os", SystemUtils.OS_NAME) - if (SystemInfo.isLinux) { - properties.put("platform", "Linux") - } else if (SystemInfo.isWindows) { - properties.put("platform", "Windows") - } else if (SystemInfo.isMacOS) { - properties.put("platform", "macOS") - } - properties.put("version", Application.getVersion()) - properties.put("language", Locale.getDefault().toString()) - val message = MessageBuilder("0871335f59ee6d0eb246b008a20f9d1c") - .event(getAnalyticsUserID(), "launch", properties) - val delivery = ClientDelivery() - delivery.addMessage(message) - val endpoints = listOf( - "https://api-eu.mixpanel.com", - "https://api-in.mixpanel.com", - "https://api.mixpanel.com", - "http://api.mixpanel.com", - ) - for (endpoint in endpoints) { - try { - MixpanelAPI( - "$endpoint/track", - "$endpoint/engage", - "$endpoint/groups" - ).deliver(delivery, true) - break - } catch (e: Exception) { - if (log.isErrorEnabled) { - log.error(e.message, e) - } - continue - } - } - } catch (e: Exception) { - if (log.isErrorEnabled) { - log.error(e.message, e) - } - } - } + MixpanelService.getInstance().push("launch") } - private fun getAnalyticsUserID(): String { - val properties = DatabaseManager.getInstance().properties - var id = properties.getString("AnalyticsUserID") - if (id.isNullOrBlank()) { - id = randomUUID() - properties.putString("AnalyticsUserID", id) - } - return id - } } \ No newline at end of file diff --git a/src/main/kotlin/app/termora/MixpanelService.kt b/src/main/kotlin/app/termora/MixpanelService.kt new file mode 100644 index 0000000..4035980 --- /dev/null +++ b/src/main/kotlin/app/termora/MixpanelService.kt @@ -0,0 +1,85 @@ +package app.termora + +import app.termora.database.DatabaseManager +import com.formdev.flatlaf.util.SystemInfo +import com.mixpanel.mixpanelapi.ClientDelivery +import com.mixpanel.mixpanelapi.MessageBuilder +import com.mixpanel.mixpanelapi.MixpanelAPI +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import org.apache.commons.lang3.SystemUtils +import org.json.JSONObject +import org.slf4j.LoggerFactory +import java.util.* + +internal class MixpanelService private constructor() { + companion object { + private val log = LoggerFactory.getLogger(MixpanelService::class.java) + + fun getInstance(): MixpanelService { + return ApplicationScope.forApplicationScope().getOrCreate(MixpanelService::class) { MixpanelService() } + } + } + + fun push(event: String, extras: Map = emptyMap()) { + swingCoroutineScope.launch(Dispatchers.IO) { + try { + val properties = JSONObject() + for (entry in extras) { + properties.put(entry.key, entry.value) + } + properties.put("os", SystemUtils.OS_NAME) + if (SystemInfo.isLinux) { + properties.put("platform", "Linux") + } else if (SystemInfo.isWindows) { + properties.put("platform", "Windows") + } else if (SystemInfo.isMacOS) { + properties.put("platform", "macOS") + } + properties.put("version", Application.getVersion()) + properties.put("language", Locale.getDefault().toString()) + val message = MessageBuilder("0871335f59ee6d0eb246b008a20f9d1c") + .event(getAnalyticsUserID(), event, properties) + val delivery = ClientDelivery() + delivery.addMessage(message) + val endpoints = listOf( + "https://api-eu.mixpanel.com", + "https://api-in.mixpanel.com", + "https://api.mixpanel.com", + "http://api.mixpanel.com", + ) + for (endpoint in endpoints) { + try { + MixpanelAPI( + "$endpoint/track", + "$endpoint/engage", + "$endpoint/groups" + ).deliver(delivery, true) + break + } catch (e: Exception) { + if (log.isErrorEnabled) { + log.error(e.message, e) + } + continue + } + } + } catch (e: Exception) { + if (log.isErrorEnabled) { + log.error(e.message, e) + } + } + } + } + + + private fun getAnalyticsUserID(): String { + val properties = DatabaseManager.getInstance().properties + var id = properties.getString("AnalyticsUserID") + if (id.isNullOrBlank()) { + id = randomUUID() + properties.putString("AnalyticsUserID", id) + } + return id + } + +} \ No newline at end of file diff --git a/src/main/kotlin/app/termora/plugin/internal/plugin/PluginPanel.kt b/src/main/kotlin/app/termora/plugin/internal/plugin/PluginPanel.kt index 30a2d5b..75cdb49 100644 --- a/src/main/kotlin/app/termora/plugin/internal/plugin/PluginPanel.kt +++ b/src/main/kotlin/app/termora/plugin/internal/plugin/PluginPanel.kt @@ -185,6 +185,13 @@ class PluginPanel(val descriptor: PluginPluginDescriptor) : JPanel(), Disposable } } + MixpanelService.getInstance().push( + "uninstall-plugin", mapOf( + "pluginName" to descriptor.plugin.getName(), + "pluginVersion" to descriptor.version.toString(), + ) + ) + // 询问是否重启 TermoraRestarter.getInstance().scheduleRestart(owner) } else { @@ -227,6 +234,13 @@ class PluginPanel(val descriptor: PluginPluginDescriptor) : JPanel(), Disposable } }, button == updateButton) + MixpanelService.getInstance().push( + "${if (button == installButton) "install" else "update"}-plugin", mapOf( + "pluginName" to descriptor.plugin.getName(), + "pluginVersion" to descriptor.version.toString(), + ) + ) + withContext(Dispatchers.Swing) { installed.add(descriptor.id)