mirror of
https://gitlab.com/2009scape/rt4-client.git
synced 2025-12-15 02:50:23 -07:00
More cleanup
This commit is contained in:
parent
47e545cbc7
commit
440b8d4de1
4 changed files with 571 additions and 482 deletions
|
|
@ -0,0 +1,473 @@
|
|||
package KondoKit
|
||||
|
||||
import KondoKit.pluginmanager.*
|
||||
import KondoKit.views.ReflectiveEditorView
|
||||
import plugin.Plugin
|
||||
import plugin.PluginInfo
|
||||
import plugin.PluginRepository
|
||||
import rt4.GlobalJsonConfig
|
||||
import java.awt.Component
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import javax.swing.*
|
||||
|
||||
class ReflectiveEditorPlugin : Plugin() {
|
||||
|
||||
// Fields that were previously in ReflectiveEditorView
|
||||
private var gitLabPlugins: List<GitLabPlugin> = listOf()
|
||||
private var pluginStatuses: List<PluginInfoWithStatus> = listOf()
|
||||
private var reloadPlugins = false // Flag for scheduled plugin reload to avoid crashes
|
||||
private val pluginsDirectory: File = File(GlobalJsonConfig.instance.pluginsFolder)
|
||||
|
||||
override fun Init() {
|
||||
// Initialize the plugin, fetch remote plugins
|
||||
GitLabPluginFetcher.fetchGitLabPlugins { plugins ->
|
||||
gitLabPlugins = plugins
|
||||
// Update plugin statuses with comparison between installed and remote plugins
|
||||
updatePluginStatuses()
|
||||
}
|
||||
}
|
||||
|
||||
// Plugin management functionality that was in ReflectiveEditorView
|
||||
fun getGitLabPlugins(): List<GitLabPlugin> = gitLabPlugins
|
||||
|
||||
fun getPluginStatuses(): List<PluginInfoWithStatus> = pluginStatuses
|
||||
|
||||
fun updatePluginStatuses() {
|
||||
val loadedPluginNames = getLoadedPluginNames()
|
||||
val statuses = mutableListOf<PluginInfoWithStatus>()
|
||||
|
||||
// Get disabled plugin names and their versions
|
||||
val disabledPluginInfo = getDisabledPluginInfo()
|
||||
|
||||
// Handle duplicate plugins (loaded and disabled) - delete the disabled version
|
||||
handleDuplicatePlugins(loadedPluginNames, disabledPluginInfo)
|
||||
|
||||
// Process remote plugins
|
||||
for (gitLabPlugin in gitLabPlugins) {
|
||||
val pluginName = gitLabPlugin.path
|
||||
// Skip KondoKit since it should always be loaded
|
||||
if (isKondoKit(pluginName)) {
|
||||
continue
|
||||
}
|
||||
val remoteVersion = gitLabPlugin.pluginProperties?.version ?: "Unknown"
|
||||
val description = gitLabPlugin.pluginProperties?.description ?: "No description available"
|
||||
val author = gitLabPlugin.pluginProperties?.author ?: "Unknown"
|
||||
|
||||
val isLoaded = loadedPluginNames.contains(pluginName)
|
||||
val isDisabled = disabledPluginInfo.containsKey(pluginName)
|
||||
val disabledVersion = disabledPluginInfo[pluginName]
|
||||
|
||||
// Check if this plugin is currently being downloaded
|
||||
val existingStatus = pluginStatuses.find { it.name == pluginName }
|
||||
val isDownloading = existingStatus?.isDownloading ?: false
|
||||
val downloadProgress = existingStatus?.downloadProgress ?: 0
|
||||
|
||||
if (isLoaded) {
|
||||
// Plugin is currently loaded
|
||||
statuses.add(PluginInfoWithStatus(
|
||||
name = pluginName,
|
||||
installedVersion = remoteVersion, // We don't have the actual installed version, but we know it's loaded
|
||||
remoteVersion = remoteVersion,
|
||||
description = description,
|
||||
author = author,
|
||||
gitLabPlugin = gitLabPlugin,
|
||||
isInstalled = true,
|
||||
needsUpdate = false, // We assume it's up-to-date since it's loaded
|
||||
isDownloading = isDownloading,
|
||||
downloadProgress = downloadProgress
|
||||
))
|
||||
} else if (isDisabled) {
|
||||
// Plugin is disabled, check if versions match
|
||||
val versionsMatch = disabledVersion != null && disabledVersion == remoteVersion
|
||||
if (!versionsMatch) {
|
||||
// Versions don't match, show update option
|
||||
statuses.add(PluginInfoWithStatus(
|
||||
name = pluginName,
|
||||
installedVersion = disabledVersion,
|
||||
remoteVersion = remoteVersion,
|
||||
description = description,
|
||||
author = author,
|
||||
gitLabPlugin = gitLabPlugin,
|
||||
isInstalled = true, // It's installed but disabled
|
||||
needsUpdate = true, // Needs update since versions don't match
|
||||
isDownloading = isDownloading,
|
||||
downloadProgress = downloadProgress
|
||||
))
|
||||
}
|
||||
// If versions match, we don't add it to the list since there's no point showing it
|
||||
} else {
|
||||
// Plugin is not installed at all
|
||||
statuses.add(PluginInfoWithStatus(
|
||||
name = pluginName,
|
||||
installedVersion = null,
|
||||
remoteVersion = remoteVersion,
|
||||
description = description,
|
||||
author = author,
|
||||
gitLabPlugin = gitLabPlugin,
|
||||
isInstalled = false,
|
||||
needsUpdate = false,
|
||||
isDownloading = isDownloading,
|
||||
downloadProgress = downloadProgress
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pluginStatuses = statuses
|
||||
}
|
||||
|
||||
// Helper method to get currently loaded plugin names
|
||||
private fun getLoadedPluginNames(): Set<String> {
|
||||
val loadedPluginNames = mutableSetOf<String>()
|
||||
|
||||
try {
|
||||
// Get loaded plugins
|
||||
val loadedPluginsField = PluginRepository::class.java.getDeclaredField("loadedPlugins")
|
||||
loadedPluginsField.isAccessible = true
|
||||
val loadedPlugins = loadedPluginsField.get(null) as HashMap<*, *>
|
||||
|
||||
for ((_, plugin) in loadedPlugins) {
|
||||
val pluginName = getPluginDirName(plugin as Plugin)
|
||||
loadedPluginNames.add(pluginName)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
return loadedPluginNames
|
||||
}
|
||||
|
||||
// Helper method to parse plugin.properties content
|
||||
private fun parsePluginProperties(content: String): PluginProperties {
|
||||
var author = "Unknown"
|
||||
var version = "Unknown"
|
||||
var description = "No description available"
|
||||
|
||||
val lines = content.split("\n")
|
||||
for (line in lines) {
|
||||
val parts = line.split("=")
|
||||
if (parts.size == 2) {
|
||||
val key = parts[0].trim()
|
||||
val value = parts[1].replace("\"", "").replace("'", "").trim()
|
||||
|
||||
when {
|
||||
key.startsWith("AUTHOR", ignoreCase = true) -> {
|
||||
author = value
|
||||
}
|
||||
key.startsWith("VERSION", ignoreCase = true) -> {
|
||||
version = value
|
||||
}
|
||||
key.startsWith("DESCRIPTION", ignoreCase = true) -> {
|
||||
description = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PluginProperties(author, version, description)
|
||||
}
|
||||
|
||||
// Helper method to get disabled plugin names and their versions
|
||||
private fun getDisabledPluginInfo(): Map<String, String> {
|
||||
val disabledPluginInfo = mutableMapOf<String, String>()
|
||||
val disabledDir = File(pluginsDirectory, "disabled")
|
||||
|
||||
if (disabledDir.exists() && disabledDir.isDirectory) {
|
||||
val disabledPlugins = disabledDir.listFiles { file -> file.isDirectory } ?: arrayOf()
|
||||
|
||||
for (pluginDir in disabledPlugins) {
|
||||
try {
|
||||
val propertiesFile = File(pluginDir, "plugin.properties")
|
||||
if (propertiesFile.exists()) {
|
||||
val content = propertiesFile.readText()
|
||||
val properties = parsePluginProperties(content)
|
||||
disabledPluginInfo[pluginDir.name] = properties.version
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return disabledPluginInfo
|
||||
}
|
||||
|
||||
// Helper method to handle duplicate plugins (loaded and disabled)
|
||||
private fun handleDuplicatePlugins(loadedPluginNames: Set<String>, disabledPluginInfo: Map<String, String>) {
|
||||
var needsReload = false
|
||||
for (pluginName in loadedPluginNames) {
|
||||
if (disabledPluginInfo.containsKey(pluginName)) {
|
||||
try {
|
||||
val disabledDir = File(pluginsDirectory, "disabled")
|
||||
val pluginDir = File(disabledDir, pluginName)
|
||||
if (pluginDir.exists() && pluginDir.isDirectory) {
|
||||
if (deleteRecursively(pluginDir)) {
|
||||
needsReload = true
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reload plugins if we deleted any disabled duplicates
|
||||
if (needsReload) {
|
||||
PluginRepository.reloadPlugins()
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to delete a plugin
|
||||
fun deletePlugin(pluginName: String, isDisabled: Boolean, mainPanel: Component) {
|
||||
try {
|
||||
val pluginDir = if (isDisabled) {
|
||||
File(File(pluginsDirectory, "disabled"), pluginName)
|
||||
} else {
|
||||
File(pluginsDirectory, pluginName)
|
||||
}
|
||||
|
||||
if (pluginDir.exists() && pluginDir.isDirectory) {
|
||||
// Recursively delete the directory
|
||||
if (deleteRecursively(pluginDir)) {
|
||||
Helpers.showToast(mainPanel, "Plugin deleted successfully", JOptionPane.INFORMATION_MESSAGE)
|
||||
|
||||
// If we deleted a loaded plugin, schedule plugin reload
|
||||
if (!isDisabled) {
|
||||
reloadPlugins = true
|
||||
}
|
||||
|
||||
// Refresh the plugin list view
|
||||
SwingUtilities.invokeLater {
|
||||
ReflectiveEditorView.addPlugins(ReflectiveEditorView.panel)
|
||||
}
|
||||
} else {
|
||||
Helpers.showToast(mainPanel, "Failed to delete plugin", JOptionPane.ERROR_MESSAGE)
|
||||
}
|
||||
} else {
|
||||
Helpers.showToast(mainPanel, "Plugin directory not found", JOptionPane.ERROR_MESSAGE)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Helpers.showToast(mainPanel, "Error deleting plugin: ${e.message}", JOptionPane.ERROR_MESSAGE)
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to recursively delete a directory
|
||||
private fun deleteRecursively(file: File): Boolean {
|
||||
if (file.isDirectory) {
|
||||
file.listFiles()?.forEach { child ->
|
||||
if (!deleteRecursively(child)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return file.delete()
|
||||
}
|
||||
|
||||
// Helper function to check if a plugin is the KondoKit plugin
|
||||
private fun isKondoKit(pluginName: String): Boolean {
|
||||
return pluginName == "KondoKit"
|
||||
}
|
||||
|
||||
// Enable a plugin by moving it from disabled to main directory
|
||||
fun enablePlugin(pluginName: String, mainPanel: Component) {
|
||||
try {
|
||||
// Source and destination directories
|
||||
val disabledDir = File(pluginsDirectory, "disabled")
|
||||
val sourceDir = File(disabledDir, pluginName)
|
||||
val destDir = File(pluginsDirectory, pluginName)
|
||||
|
||||
// Check if source directory exists
|
||||
if (!sourceDir.exists()) {
|
||||
Helpers.showToast(mainPanel, "Plugin directory not found: ${sourceDir.absolutePath}", JOptionPane.ERROR_MESSAGE)
|
||||
return
|
||||
}
|
||||
|
||||
// Move the directory
|
||||
if (sourceDir.renameTo(destDir)) {
|
||||
Helpers.showToast(mainPanel, "Plugin enabled")
|
||||
|
||||
// Schedule plugin reload to avoid crashes
|
||||
reloadPlugins = true
|
||||
|
||||
// Refresh the plugin list view
|
||||
SwingUtilities.invokeLater {
|
||||
ReflectiveEditorView.addPlugins(ReflectiveEditorView.panel)
|
||||
}
|
||||
} else {
|
||||
Helpers.showToast(mainPanel, "Failed to enable plugin", JOptionPane.ERROR_MESSAGE)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Helpers.showToast(mainPanel, "Error enabling plugin: ${e.message}", JOptionPane.ERROR_MESSAGE)
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle a plugin's enable/disable state by moving it between directories
|
||||
fun togglePlugin(plugin: Plugin, pluginInfo: PluginInfo, toggleSwitch: Component, activated: Boolean, mainPanel: Component) {
|
||||
try {
|
||||
// Get the plugin directory name from the plugin's class package
|
||||
val pluginDirName = getPluginDirName(plugin)
|
||||
|
||||
// Source and destination directories
|
||||
val sourceDir = if (activated) {
|
||||
// Moving from disabled to enabled
|
||||
File(File(pluginsDirectory, "disabled"), pluginDirName)
|
||||
} else {
|
||||
// Moving from enabled to disabled
|
||||
File(pluginsDirectory, pluginDirName)
|
||||
}
|
||||
|
||||
val destDir = if (activated) {
|
||||
// Moving to main plugins directory
|
||||
File(pluginsDirectory, pluginDirName)
|
||||
} else {
|
||||
// Moving to disabled directory
|
||||
val disabledDir = File(pluginsDirectory, "disabled")
|
||||
if (!disabledDir.exists()) {
|
||||
disabledDir.mkdirs()
|
||||
}
|
||||
File(disabledDir, pluginDirName)
|
||||
}
|
||||
|
||||
// Check if source directory exists
|
||||
if (!sourceDir.exists()) {
|
||||
Helpers.showToast(mainPanel, "Plugin directory not found: ${sourceDir.absolutePath}", JOptionPane.ERROR_MESSAGE)
|
||||
// Reset toggle switch to previous state
|
||||
SwingUtilities.invokeLater {
|
||||
if (toggleSwitch is JComponent) {
|
||||
toggleSwitch.repaint()
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Move the directory
|
||||
if (sourceDir.renameTo(destDir)) {
|
||||
Helpers.showToast(mainPanel, if (activated) "Plugin enabled" else "Plugin disabled")
|
||||
|
||||
// Schedule plugin reload to avoid crashes
|
||||
reloadPlugins = true
|
||||
|
||||
// Refresh the plugin list view
|
||||
SwingUtilities.invokeLater {
|
||||
ReflectiveEditorView.addPlugins(ReflectiveEditorView.panel)
|
||||
}
|
||||
} else {
|
||||
Helpers.showToast(mainPanel, "Failed to ${if (activated) "enable" else "disable"} plugin", JOptionPane.ERROR_MESSAGE)
|
||||
// Reset toggle switch to previous state
|
||||
SwingUtilities.invokeLater {
|
||||
if (toggleSwitch is JComponent) {
|
||||
toggleSwitch.repaint()
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
Helpers.showToast(mainPanel, "Error toggling plugin: ${e.message}", JOptionPane.ERROR_MESSAGE)
|
||||
// Reset toggle switch to previous state
|
||||
SwingUtilities.invokeLater {
|
||||
if (toggleSwitch is JComponent) {
|
||||
toggleSwitch.repaint()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to get plugin directory name from plugin instance
|
||||
private fun getPluginDirName(plugin: Plugin): String {
|
||||
// Extract the directory name from the plugin's package
|
||||
// The package name is typically like "GroundItems.plugin" so we take the first part
|
||||
val packageName = plugin.javaClass.`package`.name
|
||||
return packageName.substringBefore(".")
|
||||
}
|
||||
|
||||
// Check if a plugin is currently enabled
|
||||
fun isPluginEnabled(plugin: Plugin, pluginInfo: PluginInfo): Boolean {
|
||||
// Get the plugin directory name from the plugin's class package
|
||||
val pluginDirName = getPluginDirName(plugin)
|
||||
val pluginDir = File(pluginsDirectory, pluginDirName)
|
||||
return pluginDir.exists() && pluginDir.isDirectory
|
||||
}
|
||||
|
||||
// Method to start downloading a plugin
|
||||
fun startPluginDownload(pluginStatus: PluginInfoWithStatus, mainPanel: Component) {
|
||||
val gitLabPlugin = pluginStatus.gitLabPlugin
|
||||
if (gitLabPlugin == null) {
|
||||
Helpers.showToast(mainPanel, "Plugin information not available", JOptionPane.ERROR_MESSAGE)
|
||||
return
|
||||
}
|
||||
|
||||
// Update plugin status to show downloading
|
||||
val updatedStatuses = pluginStatuses.map {
|
||||
if (it.name == pluginStatus.name) {
|
||||
it.copy(isDownloading = true, downloadProgress = 0)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
pluginStatuses = updatedStatuses
|
||||
|
||||
// Refresh UI to show progress bar
|
||||
SwingUtilities.invokeLater {
|
||||
ReflectiveEditorView.addPlugins(ReflectiveEditorView.panel)
|
||||
}
|
||||
|
||||
// Start the download
|
||||
PluginDownloadManager.downloadPlugin(gitLabPlugin, object : PluginDownloadManager.DownloadProgressCallback {
|
||||
override fun onProgress(pluginName: String, progress: Int) {
|
||||
// Update progress in plugin statuses
|
||||
val updatedStatuses = pluginStatuses.map {
|
||||
if (it.name == pluginName) {
|
||||
it.copy(downloadProgress = progress)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
pluginStatuses = updatedStatuses
|
||||
|
||||
// Refresh UI to show progress
|
||||
SwingUtilities.invokeLater {
|
||||
ReflectiveEditorView.addPlugins(ReflectiveEditorView.panel)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onComplete(pluginName: String, success: Boolean, errorMessage: String?) {
|
||||
// Update plugin status
|
||||
val updatedStatuses = pluginStatuses.map {
|
||||
if (it.name == pluginName) {
|
||||
it.copy(isDownloading = false, downloadProgress = if (success) 100 else 0)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
pluginStatuses = updatedStatuses
|
||||
|
||||
// Show result to user
|
||||
if (success) {
|
||||
Helpers.showToast(mainPanel, "Plugin downloaded successfully!", JOptionPane.INFORMATION_MESSAGE)
|
||||
// Reload plugins to make the newly downloaded plugin available
|
||||
PluginRepository.reloadPlugins()
|
||||
} else {
|
||||
Helpers.showToast(mainPanel, "Failed to download plugin: ${errorMessage ?: "Unknown error"}", JOptionPane.ERROR_MESSAGE)
|
||||
}
|
||||
|
||||
// Refresh UI
|
||||
SwingUtilities.invokeLater {
|
||||
ReflectiveEditorView.addPlugins(ReflectiveEditorView.panel)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Getter for plugin directory - needed for the view
|
||||
fun getPluginsDirectory(): File = pluginsDirectory
|
||||
|
||||
// Getter for reload flag - needed for the view
|
||||
fun shouldReloadPlugins(): Boolean = reloadPlugins
|
||||
|
||||
// Setter for reload flag - needed for the view
|
||||
fun setReloadPlugins(reload: Boolean) {
|
||||
reloadPlugins = reload
|
||||
}
|
||||
}
|
||||
|
|
@ -22,7 +22,7 @@ object ViewConstants {
|
|||
val DIMENSION_SMALL_ICON = Dimension(12, 12)
|
||||
val DIMENSION_LARGE_ICON = Dimension(30, 30)
|
||||
val DEFAULT_WIDGET_SIZE = Dimension(234, 50)
|
||||
val PLUGIN_LIST_ITEM_SIZE = Dimension(DEFAULT_WIDGET_SIZE.width, 30)
|
||||
val PLUGIN_LIST_ITEM_SIZE = Dimension(DEFAULT_WIDGET_SIZE.width, 36)
|
||||
val TOGGLE_PLACEHOLDER_SIZE = Dimension(60, 24)
|
||||
val TOTAL_XP_WIDGET_SIZE = Dimension(DEFAULT_WIDGET_SIZE.width, 42)
|
||||
val IMAGE_SIZE = Dimension(25, 23)
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ object PluginDownloadManager {
|
|||
debugLog("Input stream available for plugin: ${plugin.path}")
|
||||
|
||||
// Create output directory
|
||||
val pluginsDir = ReflectiveEditorView.pluginsDirectory
|
||||
val pluginsDir = File(rt4.GlobalJsonConfig.instance.pluginsFolder)
|
||||
debugLog("Plugins directory: ${pluginsDir.absolutePath}")
|
||||
|
||||
// Validate plugins directory
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import KondoKit.components.*
|
|||
import KondoKit.ViewConstants
|
||||
import KondoKit.views.ViewLayoutHelpers.createSearchFieldSection
|
||||
import KondoKit.setFixedSize
|
||||
import KondoKit.ReflectiveEditorPlugin
|
||||
import KondoKit.pluginmanager.GitLabPlugin
|
||||
import KondoKit.pluginmanager.GitLabPluginFetcher
|
||||
import KondoKit.pluginmanager.PluginDownloadManager
|
||||
|
|
@ -41,17 +42,11 @@ object ReflectiveEditorView : View {
|
|||
const val VIEW_NAME = "REFLECTIVE_EDITOR_VIEW"
|
||||
const val PLUGIN_LIST_VIEW = "PLUGIN_LIST"
|
||||
const val PLUGIN_DETAIL_VIEW = "PLUGIN_DETAIL"
|
||||
val pluginsDirectory: File = File(GlobalJsonConfig.instance.pluginsFolder)
|
||||
|
||||
private var gitLabPlugins: List<GitLabPlugin> = listOf()
|
||||
private val reflectiveEditorPlugin = ReflectiveEditorPlugin()
|
||||
|
||||
private var pluginStatuses: List<PluginInfoWithStatus> = listOf()
|
||||
|
||||
private var searchField: SearchField? = null
|
||||
|
||||
// Flag for scheduled plugin reload to avoid crashes
|
||||
private var reloadPlugins = false
|
||||
|
||||
// Helper function to check if a plugin is the KondoKit plugin
|
||||
private fun isKondoKit(pluginName: String): Boolean {
|
||||
return pluginName == "KondoKit"
|
||||
|
|
@ -75,6 +70,8 @@ object ReflectiveEditorView : View {
|
|||
get() = reflectiveEditorView ?: JPanel()
|
||||
|
||||
override fun createView() {
|
||||
// Initialize the plugin
|
||||
reflectiveEditorPlugin.Init()
|
||||
createReflectiveEditorView()
|
||||
}
|
||||
|
||||
|
|
@ -102,12 +99,7 @@ object ReflectiveEditorView : View {
|
|||
|
||||
cardLayout.show(mainPanel, PLUGIN_LIST_VIEW)
|
||||
|
||||
GitLabPluginFetcher.fetchGitLabPlugins { plugins ->
|
||||
gitLabPlugins = plugins
|
||||
// Update plugin statuses with comparison between installed and remote plugins
|
||||
updatePluginStatuses()
|
||||
// We'll update the UI when needed
|
||||
}
|
||||
// Plugin initialization is handled by the plugin class, gitLabPlugins will be fetched automatically
|
||||
}
|
||||
|
||||
private fun createPluginListView(): JPanel {
|
||||
|
|
@ -224,7 +216,7 @@ object ReflectiveEditorView : View {
|
|||
e.printStackTrace()
|
||||
}
|
||||
|
||||
val disabledDir = File(pluginsDirectory, "disabled")
|
||||
val disabledDir = File(reflectiveEditorPlugin.getPluginsDirectory(), "disabled")
|
||||
if (disabledDir.exists() && disabledDir.isDirectory) {
|
||||
val disabledPlugins = disabledDir.listFiles { file -> file.isDirectory } ?: arrayOf()
|
||||
|
||||
|
|
@ -241,7 +233,7 @@ object ReflectiveEditorView : View {
|
|||
}
|
||||
|
||||
if (pluginSearchText.isNotBlank()) {
|
||||
val matchingPluginStatuses = pluginStatuses.filter { pluginStatus ->
|
||||
val matchingPluginStatuses = reflectiveEditorPlugin.getPluginStatuses().filter { pluginStatus ->
|
||||
!pluginStatus.isInstalled &&
|
||||
!isKondoKit(pluginStatus.name) &&
|
||||
(pluginStatus.name.contains(pluginSearchText, ignoreCase = true) ||
|
||||
|
|
@ -285,6 +277,10 @@ object ReflectiveEditorView : View {
|
|||
val panel = WidgetPanel(
|
||||
widgetWidth = ViewConstants.PLUGIN_LIST_ITEM_SIZE.width,
|
||||
widgetHeight = ViewConstants.PLUGIN_LIST_ITEM_SIZE.height,
|
||||
paddingLeft = 10,
|
||||
paddingRight = 10,
|
||||
paddingTop = 10,
|
||||
paddingBottom = 10,
|
||||
addDefaultPadding = false
|
||||
).apply {
|
||||
layout = BorderLayout()
|
||||
|
|
@ -326,7 +322,7 @@ object ReflectiveEditorView : View {
|
|||
infoPanel.background = WIDGET_COLOR
|
||||
infoPanel.add(nameLabel, BorderLayout.WEST)
|
||||
|
||||
val controlsPanel = JPanel(FlowLayout(FlowLayout.RIGHT, 5, 0))
|
||||
val controlsPanel = JPanel(FlowLayout(FlowLayout.RIGHT, 5, -3))
|
||||
controlsPanel.background = WIDGET_COLOR
|
||||
|
||||
editButton?.let { controlsPanel.add(it) }
|
||||
|
|
@ -350,6 +346,10 @@ object ReflectiveEditorView : View {
|
|||
val panel = WidgetPanel(
|
||||
widgetWidth = ViewConstants.PLUGIN_LIST_ITEM_SIZE.width,
|
||||
widgetHeight = ViewConstants.PLUGIN_LIST_ITEM_SIZE.height,
|
||||
paddingLeft = 10,
|
||||
paddingRight = 10,
|
||||
paddingTop = 10,
|
||||
paddingBottom = 10,
|
||||
addDefaultPadding = false
|
||||
).apply {
|
||||
layout = BorderLayout()
|
||||
|
|
@ -365,7 +365,7 @@ object ReflectiveEditorView : View {
|
|||
toggleSwitch.setActivated(false)
|
||||
toggleSwitch.onToggleListener = { activated ->
|
||||
if (activated) {
|
||||
enablePlugin(pluginName)
|
||||
reflectiveEditorPlugin.enablePlugin(pluginName, mainPanel ?: JPanel())
|
||||
}
|
||||
// If trying to disable an already disabled plugin, reset the toggle
|
||||
else {
|
||||
|
|
@ -378,7 +378,7 @@ object ReflectiveEditorView : View {
|
|||
infoPanel.background = WIDGET_COLOR
|
||||
infoPanel.add(nameLabel, BorderLayout.WEST)
|
||||
|
||||
val controlsPanel = JPanel(FlowLayout(FlowLayout.RIGHT, 5, 0))
|
||||
val controlsPanel = JPanel(FlowLayout(FlowLayout.RIGHT, 0, 0))
|
||||
controlsPanel.background = WIDGET_COLOR
|
||||
controlsPanel.add(toggleSwitch)
|
||||
|
||||
|
|
@ -398,6 +398,10 @@ object ReflectiveEditorView : View {
|
|||
val panel = WidgetPanel(
|
||||
widgetWidth = ViewConstants.PLUGIN_LIST_ITEM_SIZE.width,
|
||||
widgetHeight = ViewConstants.PLUGIN_LIST_ITEM_SIZE.height,
|
||||
paddingLeft = 10,
|
||||
paddingRight = 10,
|
||||
paddingTop = 10,
|
||||
paddingBottom = 10,
|
||||
addDefaultPadding = false
|
||||
).apply {
|
||||
layout = BorderLayout()
|
||||
|
|
@ -453,10 +457,71 @@ object ReflectiveEditorView : View {
|
|||
|
||||
if (pluginStatus.isInstalled && !pluginStatus.needsUpdate) {
|
||||
toggleSwitch.onToggleListener = { activated ->
|
||||
// TODO: Implement enable/disable functionality
|
||||
showToast(mainPanel, "Enable/disable functionality not yet implemented", JOptionPane.INFORMATION_MESSAGE)
|
||||
// Reset for now since functionality not implemented
|
||||
toggleSwitch.setActivated(true)
|
||||
// Find the corresponding loaded plugin to use toggle functionality
|
||||
val loadedPluginsField = PluginRepository::class.java.getDeclaredField("loadedPlugins")
|
||||
loadedPluginsField.isAccessible = true
|
||||
val loadedPlugins = loadedPluginsField.get(null) as HashMap<*, *>
|
||||
|
||||
var foundPlugin: Plugin? = null
|
||||
var foundPluginInfo: PluginInfo? = null
|
||||
|
||||
for ((pluginInfo, plugin) in loadedPlugins) {
|
||||
if (getPluginDirName(plugin as Plugin) == pluginStatus.name) {
|
||||
foundPlugin = plugin
|
||||
foundPluginInfo = pluginInfo as PluginInfo
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (foundPlugin != null && foundPluginInfo != null) {
|
||||
reflectiveEditorPlugin.togglePlugin(foundPlugin, foundPluginInfo, toggleSwitch, activated, mainPanel ?: JPanel())
|
||||
} else {
|
||||
// Fallback for plugins that don't have loaded instances available
|
||||
val pluginDirName = pluginStatus.name
|
||||
val sourceDir = if (activated) {
|
||||
// Moving from disabled to enabled
|
||||
File(File(reflectiveEditorPlugin.getPluginsDirectory(), "disabled"), pluginDirName)
|
||||
} else {
|
||||
// Moving from enabled to disabled
|
||||
File(reflectiveEditorPlugin.getPluginsDirectory(), pluginDirName)
|
||||
}
|
||||
|
||||
val destDir = if (activated) {
|
||||
// Moving to main plugins directory
|
||||
File(reflectiveEditorPlugin.getPluginsDirectory(), pluginDirName)
|
||||
} else {
|
||||
// Moving to disabled directory
|
||||
val disabledDir = File(reflectiveEditorPlugin.getPluginsDirectory(), "disabled")
|
||||
if (!disabledDir.exists()) {
|
||||
disabledDir.mkdirs()
|
||||
}
|
||||
File(disabledDir, pluginDirName)
|
||||
}
|
||||
|
||||
// Check if source directory exists
|
||||
if (!sourceDir.exists()) {
|
||||
showToast(mainPanel, "Plugin directory not found: ${sourceDir.absolutePath}", JOptionPane.ERROR_MESSAGE)
|
||||
// Reset toggle switch to previous state
|
||||
toggleSwitch.setActivated(!activated)
|
||||
} else {
|
||||
// Move the directory
|
||||
if (sourceDir.renameTo(destDir)) {
|
||||
showToast(mainPanel, if (activated) "Plugin enabled" else "Plugin disabled")
|
||||
|
||||
// Schedule plugin reload to avoid crashes
|
||||
reflectiveEditorPlugin.setReloadPlugins(true)
|
||||
|
||||
// Refresh the plugin list view
|
||||
SwingUtilities.invokeLater {
|
||||
addPlugins(reflectiveEditorView!!)
|
||||
}
|
||||
} else {
|
||||
showToast(mainPanel, "Failed to ${if (activated) "enable" else "disable"} plugin", JOptionPane.ERROR_MESSAGE)
|
||||
// Reset toggle switch to previous state
|
||||
toggleSwitch.setActivated(!activated)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Hide the toggle switch for non-installed plugins
|
||||
|
|
@ -468,7 +533,7 @@ object ReflectiveEditorView : View {
|
|||
infoPanel.background = WIDGET_COLOR
|
||||
infoPanel.add(nameLabel, BorderLayout.WEST)
|
||||
|
||||
val controlsPanel = JPanel(FlowLayout(FlowLayout.RIGHT, 5, 0))
|
||||
val controlsPanel = JPanel(FlowLayout(FlowLayout.RIGHT, 0, 0))
|
||||
controlsPanel.background = WIDGET_COLOR
|
||||
controlsPanel.add(actionButton)
|
||||
controlsPanel.add(progressBar)
|
||||
|
|
@ -524,60 +589,22 @@ object ReflectiveEditorView : View {
|
|||
.replace(">", ">")
|
||||
}
|
||||
|
||||
private fun enablePlugin(pluginName: String) {
|
||||
try {
|
||||
// Source and destination directories
|
||||
val disabledDir = File(pluginsDirectory, "disabled")
|
||||
val sourceDir = File(disabledDir, pluginName)
|
||||
val destDir = File(pluginsDirectory, pluginName)
|
||||
|
||||
// Check if source directory exists
|
||||
if (!sourceDir.exists()) {
|
||||
showToast(mainPanel, "Plugin directory not found: ${sourceDir.absolutePath}", JOptionPane.ERROR_MESSAGE)
|
||||
return
|
||||
}
|
||||
|
||||
// Move the directory
|
||||
if (sourceDir.renameTo(destDir)) {
|
||||
showToast(mainPanel, "Plugin enabled")
|
||||
|
||||
// Schedule plugin reload to avoid crashes
|
||||
reloadPlugins = true
|
||||
|
||||
// Refresh the plugin list view
|
||||
SwingUtilities.invokeLater {
|
||||
addPlugins(reflectiveEditorView!!)
|
||||
}
|
||||
} else {
|
||||
showToast(mainPanel, "Failed to enable plugin", JOptionPane.ERROR_MESSAGE)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
showToast(mainPanel, "Error enabling plugin: ${e.message}", JOptionPane.ERROR_MESSAGE)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun createToggleSwitch(plugin: Plugin, pluginInfo: PluginInfo): ToggleSwitch {
|
||||
val toggleSwitch = ToggleSwitch()
|
||||
|
||||
// Set initial state
|
||||
toggleSwitch.setActivated(isPluginEnabled(plugin, pluginInfo))
|
||||
toggleSwitch.setActivated(reflectiveEditorPlugin.isPluginEnabled(plugin, pluginInfo))
|
||||
|
||||
// Add toggle listener
|
||||
toggleSwitch.onToggleListener = { activated ->
|
||||
togglePlugin(plugin, pluginInfo, toggleSwitch, activated)
|
||||
reflectiveEditorPlugin.togglePlugin(plugin, pluginInfo, toggleSwitch, activated, mainPanel ?: JPanel())
|
||||
}
|
||||
|
||||
return toggleSwitch
|
||||
}
|
||||
|
||||
private fun isPluginEnabled(plugin: Plugin, pluginInfo: PluginInfo): Boolean {
|
||||
// Get the plugin directory name from the plugin's class package
|
||||
val pluginDirName = getPluginDirName(plugin)
|
||||
val pluginDir = File(pluginsDirectory, pluginDirName)
|
||||
return pluginDir.exists() && pluginDir.isDirectory
|
||||
}
|
||||
|
||||
private fun getPluginDirName(plugin: Plugin): String {
|
||||
// Extract the directory name from the plugin's package
|
||||
// The package name is typically like "GroundItems.plugin" so we take the first part
|
||||
|
|
@ -585,64 +612,6 @@ object ReflectiveEditorView : View {
|
|||
return packageName.substringBefore(".")
|
||||
}
|
||||
|
||||
private fun togglePlugin(plugin: Plugin, pluginInfo: PluginInfo, toggleSwitch: ToggleSwitch, activated: Boolean) {
|
||||
try {
|
||||
// Get the plugin directory name from the plugin's class package
|
||||
val pluginDirName = getPluginDirName(plugin)
|
||||
|
||||
// Source and destination directories
|
||||
val sourceDir = if (activated) {
|
||||
// Moving from disabled to enabled
|
||||
File(File(pluginsDirectory, "disabled"), pluginDirName)
|
||||
} else {
|
||||
// Moving from enabled to disabled
|
||||
File(pluginsDirectory, pluginDirName)
|
||||
}
|
||||
|
||||
val destDir = if (activated) {
|
||||
// Moving to main plugins directory
|
||||
File(pluginsDirectory, pluginDirName)
|
||||
} else {
|
||||
// Moving to disabled directory
|
||||
val disabledDir = File(pluginsDirectory, "disabled")
|
||||
if (!disabledDir.exists()) {
|
||||
disabledDir.mkdirs()
|
||||
}
|
||||
File(disabledDir, pluginDirName)
|
||||
}
|
||||
|
||||
// Check if source directory exists
|
||||
if (!sourceDir.exists()) {
|
||||
showToast(mainPanel, "Plugin directory not found: ${sourceDir.absolutePath}", JOptionPane.ERROR_MESSAGE)
|
||||
// Reset toggle switch to previous state
|
||||
toggleSwitch.setActivated(!activated)
|
||||
return
|
||||
}
|
||||
|
||||
// Move the directory
|
||||
if (sourceDir.renameTo(destDir)) {
|
||||
showToast(mainPanel, if (activated) "Plugin enabled" else "Plugin disabled")
|
||||
|
||||
// Schedule plugin reload to avoid crashes
|
||||
reloadPlugins = true
|
||||
|
||||
// Refresh the plugin list view
|
||||
SwingUtilities.invokeLater {
|
||||
addPlugins(reflectiveEditorView!!)
|
||||
}
|
||||
} else {
|
||||
showToast(mainPanel, "Failed to ${if (activated) "enable" else "disable"} plugin", JOptionPane.ERROR_MESSAGE)
|
||||
// Reset toggle switch to previous state
|
||||
toggleSwitch.setActivated(!activated)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
showToast(mainPanel, "Error toggling plugin: ${e.message}", JOptionPane.ERROR_MESSAGE)
|
||||
// Reset toggle switch to previous state
|
||||
toggleSwitch.setActivated(!activated)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showPluginDetails(pluginInfo: PluginInfo, plugin: Plugin) {
|
||||
currentPluginInfo = pluginInfo
|
||||
currentPlugin = plugin
|
||||
|
|
@ -775,13 +744,13 @@ object ReflectiveEditorView : View {
|
|||
}
|
||||
|
||||
// Check if we need to reload plugins
|
||||
if (reloadPlugins) {
|
||||
if (reflectiveEditorPlugin.shouldReloadPlugins()) {
|
||||
PluginRepository.reloadPlugins()
|
||||
reloadPlugins = false
|
||||
reflectiveEditorPlugin.setReloadPlugins(false)
|
||||
}
|
||||
|
||||
// Update plugin statuses to reflect current loaded plugins
|
||||
updatePluginStatuses()
|
||||
reflectiveEditorPlugin.updatePluginStatuses()
|
||||
|
||||
val contentPanel = pluginListContentPanel
|
||||
if (contentPanel == null) {
|
||||
|
|
@ -815,104 +784,6 @@ object ReflectiveEditorView : View {
|
|||
mainPanel.revalidate()
|
||||
mainPanel.repaint()
|
||||
}
|
||||
|
||||
var customToolTipWindow: JWindow? = null
|
||||
|
||||
fun showCustomToolTip(text: String, component: JComponent) {
|
||||
val tooltipFont = ViewConstants.FONT_RUNESCAPE_SMALL_PLAIN_16
|
||||
val maxWidth = 150
|
||||
|
||||
// Create a dummy JLabel to get FontMetrics for the font used in the tooltip
|
||||
val dummyLabel = JLabel()
|
||||
dummyLabel.font = tooltipFont
|
||||
val fontMetrics = dummyLabel.getFontMetrics(tooltipFont)
|
||||
val lineHeight = fontMetrics.height
|
||||
|
||||
// Calculate the approximate width of the text
|
||||
val textWidth = fontMetrics.stringWidth(text)
|
||||
|
||||
// Calculate the number of lines required based on the text width and max tooltip width
|
||||
val numberOfLines = ceil(textWidth.toDouble() / maxWidth).toInt()
|
||||
|
||||
// Calculate the required height of the tooltip
|
||||
val requiredHeight = numberOfLines * lineHeight + 6 // Adding some padding
|
||||
|
||||
if (customToolTipWindow == null) {
|
||||
customToolTipWindow = JWindow().apply {
|
||||
val bgColor = Helpers.colorToHex(TOOLTIP_BACKGROUND)
|
||||
val textColor = Helpers.colorToHex(secondaryColor)
|
||||
contentPane = JLabel("<html><div style='color: $textColor; background-color: $bgColor; padding: 3px; word-break: break-all;'>$text</div></html>").apply {
|
||||
border = BorderFactory.createLineBorder(Color.BLACK)
|
||||
isOpaque = true
|
||||
background = TOOLTIP_BACKGROUND
|
||||
foreground = Color.WHITE
|
||||
font = tooltipFont
|
||||
maximumSize = Dimension(maxWidth, Int.MAX_VALUE)
|
||||
preferredSize = Dimension(maxWidth, requiredHeight)
|
||||
}
|
||||
pack()
|
||||
}
|
||||
} else {
|
||||
// Update the tooltip text
|
||||
val label = customToolTipWindow!!.contentPane as JLabel
|
||||
val bgColor = Helpers.colorToHex(TOOLTIP_BACKGROUND)
|
||||
val textColor = Helpers.colorToHex(secondaryColor)
|
||||
label.text = "<html><div style='color: $textColor; background-color: $bgColor; padding: 3px; word-break: break-all;'>$text</div></html>"
|
||||
label.preferredSize = Dimension(maxWidth, requiredHeight)
|
||||
customToolTipWindow!!.pack()
|
||||
}
|
||||
|
||||
// Position the tooltip near the component
|
||||
val locationOnScreen = component.locationOnScreen
|
||||
customToolTipWindow!!.setLocation(locationOnScreen.x, locationOnScreen.y + 15)
|
||||
customToolTipWindow!!.isVisible = true
|
||||
}
|
||||
|
||||
// Add this helper function to read plugin properties from a disabled plugin directory
|
||||
private fun readDisabledPluginProperties(pluginName: String): PluginProperties? {
|
||||
try {
|
||||
val disabledDir = File(pluginsDirectory, "disabled")
|
||||
val pluginDir = File(disabledDir, pluginName)
|
||||
val propertiesFile = File(pluginDir, "plugin.properties")
|
||||
|
||||
if (propertiesFile.exists()) {
|
||||
val content = propertiesFile.readText()
|
||||
return parsePluginProperties(content)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// Helper function to parse plugin.properties content
|
||||
private fun parsePluginProperties(content: String): PluginProperties {
|
||||
var author = "Unknown"
|
||||
var version = "Unknown"
|
||||
var description = "No description available"
|
||||
|
||||
val lines = content.split("\n")
|
||||
for (line in lines) {
|
||||
val parts = line.split("=")
|
||||
if (parts.size == 2) {
|
||||
val key = parts[0].trim()
|
||||
val value = parts[1].replace("\"", "").replace("'", "").trim()
|
||||
|
||||
when {
|
||||
key.startsWith("AUTHOR", ignoreCase = true) -> {
|
||||
author = value
|
||||
}
|
||||
key.startsWith("VERSION", ignoreCase = true) -> {
|
||||
version = value
|
||||
}
|
||||
key.startsWith("DESCRIPTION", ignoreCase = true) -> {
|
||||
description = value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PluginProperties(author, version, description)
|
||||
}
|
||||
|
||||
// Helper method to find and reset ScrollablePanel components within a container
|
||||
private fun findAndResetScrollablePanel(container: Component) {
|
||||
|
|
@ -925,234 +796,9 @@ object ReflectiveEditorView : View {
|
|||
}
|
||||
}
|
||||
|
||||
// Helper method to get currently loaded plugin names
|
||||
private fun getLoadedPluginNames(): Set<String> {
|
||||
val loadedPluginNames = mutableSetOf<String>()
|
||||
|
||||
try {
|
||||
// Get loaded plugins
|
||||
val loadedPluginsField = PluginRepository::class.java.getDeclaredField("loadedPlugins")
|
||||
loadedPluginsField.isAccessible = true
|
||||
val loadedPlugins = loadedPluginsField.get(null) as HashMap<*, *>
|
||||
|
||||
|
||||
for ((_, plugin) in loadedPlugins) {
|
||||
val pluginName = getPluginDirName(plugin as Plugin)
|
||||
loadedPluginNames.add(pluginName)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
return loadedPluginNames
|
||||
}
|
||||
|
||||
// Method to start downloading a plugin
|
||||
private fun startPluginDownload(pluginStatus: PluginInfoWithStatus) {
|
||||
val gitLabPlugin = pluginStatus.gitLabPlugin
|
||||
if (gitLabPlugin == null) {
|
||||
showToast(mainPanel, "Plugin information not available", JOptionPane.ERROR_MESSAGE)
|
||||
return
|
||||
}
|
||||
|
||||
// Log the download URL for debugging
|
||||
val downloadUrl = PluginDownloadManager.getDownloadUrlForLogging(gitLabPlugin)
|
||||
|
||||
// Update plugin status to show downloading
|
||||
val updatedStatuses = pluginStatuses.map {
|
||||
if (it.name == pluginStatus.name) {
|
||||
it.copy(isDownloading = true, downloadProgress = 0)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
pluginStatuses = updatedStatuses
|
||||
|
||||
// Refresh UI to show progress bar
|
||||
SwingUtilities.invokeLater {
|
||||
addPlugins(reflectiveEditorView!!)
|
||||
}
|
||||
|
||||
// Start the download
|
||||
PluginDownloadManager.downloadPlugin(gitLabPlugin, object : PluginDownloadManager.DownloadProgressCallback {
|
||||
override fun onProgress(pluginName: String, progress: Int) {
|
||||
// Update progress in plugin statuses
|
||||
val updatedStatuses = pluginStatuses.map {
|
||||
if (it.name == pluginName) {
|
||||
it.copy(downloadProgress = progress)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
pluginStatuses = updatedStatuses
|
||||
|
||||
// Refresh UI to show progress
|
||||
SwingUtilities.invokeLater {
|
||||
addPlugins(reflectiveEditorView!!)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onComplete(pluginName: String, success: Boolean, errorMessage: String?) {
|
||||
// Update plugin status
|
||||
val updatedStatuses = pluginStatuses.map {
|
||||
if (it.name == pluginName) {
|
||||
it.copy(isDownloading = false, downloadProgress = if (success) 100 else 0)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
pluginStatuses = updatedStatuses
|
||||
|
||||
// Show result to user
|
||||
if (success) {
|
||||
showToast(mainPanel, "Plugin downloaded successfully!", JOptionPane.INFORMATION_MESSAGE)
|
||||
// Reload plugins to make the newly downloaded plugin available
|
||||
PluginRepository.reloadPlugins()
|
||||
} else {
|
||||
showToast(mainPanel, "Failed to download plugin: ${errorMessage ?: "Unknown error"}", JOptionPane.ERROR_MESSAGE)
|
||||
}
|
||||
|
||||
// Refresh UI
|
||||
SwingUtilities.invokeLater {
|
||||
addPlugins(reflectiveEditorView!!)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Update plugin statuses by comparing installed and remote plugins
|
||||
private fun updatePluginStatuses() {
|
||||
val loadedPluginNames = getLoadedPluginNames()
|
||||
val statuses = mutableListOf<PluginInfoWithStatus>()
|
||||
|
||||
|
||||
// Get disabled plugin names and their versions
|
||||
val disabledPluginInfo = getDisabledPluginInfo()
|
||||
|
||||
// Handle duplicate plugins (loaded and disabled) - delete the disabled version
|
||||
handleDuplicatePlugins(loadedPluginNames, disabledPluginInfo)
|
||||
|
||||
// Process remote plugins
|
||||
for (gitLabPlugin in gitLabPlugins) {
|
||||
val pluginName = gitLabPlugin.path
|
||||
// Skip KondoKit since it should always be loaded
|
||||
if (isKondoKit(pluginName)) {
|
||||
continue
|
||||
}
|
||||
val remoteVersion = gitLabPlugin.pluginProperties?.version ?: "Unknown"
|
||||
val description = gitLabPlugin.pluginProperties?.description ?: "No description available"
|
||||
val author = gitLabPlugin.pluginProperties?.author ?: "Unknown"
|
||||
|
||||
val isLoaded = loadedPluginNames.contains(pluginName)
|
||||
val isDisabled = disabledPluginInfo.containsKey(pluginName)
|
||||
val disabledVersion = disabledPluginInfo[pluginName]
|
||||
|
||||
|
||||
// Check if this plugin is currently being downloaded
|
||||
val existingStatus = pluginStatuses.find { it.name == pluginName }
|
||||
val isDownloading = existingStatus?.isDownloading ?: false
|
||||
val downloadProgress = existingStatus?.downloadProgress ?: 0
|
||||
|
||||
if (isLoaded) {
|
||||
// Plugin is currently loaded
|
||||
statuses.add(PluginInfoWithStatus(
|
||||
name = pluginName,
|
||||
installedVersion = remoteVersion, // We don't have the actual installed version, but we know it's loaded
|
||||
remoteVersion = remoteVersion,
|
||||
description = description,
|
||||
author = author,
|
||||
gitLabPlugin = gitLabPlugin,
|
||||
isInstalled = true,
|
||||
needsUpdate = false, // We assume it's up-to-date since it's loaded
|
||||
isDownloading = isDownloading,
|
||||
downloadProgress = downloadProgress
|
||||
))
|
||||
} else if (isDisabled) {
|
||||
// Plugin is disabled, check if versions match
|
||||
val versionsMatch = disabledVersion != null && disabledVersion == remoteVersion
|
||||
if (!versionsMatch) {
|
||||
// Versions don't match, show update option
|
||||
statuses.add(PluginInfoWithStatus(
|
||||
name = pluginName,
|
||||
installedVersion = disabledVersion,
|
||||
remoteVersion = remoteVersion,
|
||||
description = description,
|
||||
author = author,
|
||||
gitLabPlugin = gitLabPlugin,
|
||||
isInstalled = true, // It's installed but disabled
|
||||
needsUpdate = true, // Needs update since versions don't match
|
||||
isDownloading = isDownloading,
|
||||
downloadProgress = downloadProgress
|
||||
))
|
||||
}
|
||||
// If versions match, we don't add it to the list since there's no point showing it
|
||||
} else {
|
||||
// Plugin is not installed at all
|
||||
statuses.add(PluginInfoWithStatus(
|
||||
name = pluginName,
|
||||
installedVersion = null,
|
||||
remoteVersion = remoteVersion,
|
||||
description = description,
|
||||
author = author,
|
||||
gitLabPlugin = gitLabPlugin,
|
||||
isInstalled = false,
|
||||
needsUpdate = false,
|
||||
isDownloading = isDownloading,
|
||||
downloadProgress = downloadProgress
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pluginStatuses = statuses
|
||||
}
|
||||
|
||||
// Helper method to handle duplicate plugins (loaded and disabled)
|
||||
private fun handleDuplicatePlugins(loadedPluginNames: Set<String>, disabledPluginInfo: Map<String, String>) {
|
||||
var needsReload = false
|
||||
for (pluginName in loadedPluginNames) {
|
||||
if (disabledPluginInfo.containsKey(pluginName)) {
|
||||
try {
|
||||
val disabledDir = File(pluginsDirectory, "disabled")
|
||||
val pluginDir = File(disabledDir, pluginName)
|
||||
if (pluginDir.exists() && pluginDir.isDirectory) {
|
||||
if (deleteRecursively(pluginDir)) {
|
||||
needsReload = true
|
||||
} else {
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reload plugins if we deleted any disabled duplicates
|
||||
if (needsReload) {
|
||||
PluginRepository.reloadPlugins()
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to get disabled plugin names and their versions
|
||||
private fun getDisabledPluginInfo(): Map<String, String> {
|
||||
val disabledPluginInfo = mutableMapOf<String, String>()
|
||||
val disabledDir = File(pluginsDirectory, "disabled")
|
||||
|
||||
if (disabledDir.exists() && disabledDir.isDirectory) {
|
||||
val disabledPlugins = disabledDir.listFiles { file -> file.isDirectory } ?: arrayOf()
|
||||
|
||||
for (pluginDir in disabledPlugins) {
|
||||
try {
|
||||
val propertiesFile = File(pluginDir, "plugin.properties")
|
||||
if (propertiesFile.exists()) {
|
||||
val content = propertiesFile.readText()
|
||||
val properties = parsePluginProperties(content)
|
||||
disabledPluginInfo[pluginDir.name] = properties.version
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return disabledPluginInfo
|
||||
reflectiveEditorPlugin.startPluginDownload(pluginStatus, mainPanel ?: JPanel())
|
||||
}
|
||||
|
||||
// Helper method to add context menu to a panel
|
||||
|
|
@ -1187,37 +833,7 @@ object ReflectiveEditorView : View {
|
|||
|
||||
// Helper method to delete a plugin
|
||||
private fun deletePlugin(pluginName: String, isDisabled: Boolean) {
|
||||
try {
|
||||
val pluginDir = if (isDisabled) {
|
||||
File(File(pluginsDirectory, "disabled"), pluginName)
|
||||
} else {
|
||||
File(pluginsDirectory, pluginName)
|
||||
}
|
||||
|
||||
if (pluginDir.exists() && pluginDir.isDirectory) {
|
||||
// Recursively delete the directory
|
||||
if (deleteRecursively(pluginDir)) {
|
||||
showToast(mainPanel, "Plugin deleted successfully", JOptionPane.INFORMATION_MESSAGE)
|
||||
|
||||
// If we deleted a loaded plugin, schedule plugin reload
|
||||
if (!isDisabled) {
|
||||
reloadPlugins = true
|
||||
}
|
||||
|
||||
// Refresh the plugin list view
|
||||
SwingUtilities.invokeLater {
|
||||
addPlugins(reflectiveEditorView!!)
|
||||
}
|
||||
} else {
|
||||
showToast(mainPanel, "Failed to delete plugin", JOptionPane.ERROR_MESSAGE)
|
||||
}
|
||||
} else {
|
||||
showToast(mainPanel, "Plugin directory not found", JOptionPane.ERROR_MESSAGE)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
showToast(mainPanel, "Error deleting plugin: ${e.message}", JOptionPane.ERROR_MESSAGE)
|
||||
}
|
||||
reflectiveEditorPlugin.deletePlugin(pluginName, isDisabled, mainPanel ?: JPanel())
|
||||
}
|
||||
|
||||
// Helper method to recursively delete a directory
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue