diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index b0b03b9..a67175f 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -43,8 +43,6 @@ annotation class Exposed(val description: String = "") class plugin : Plugin() { companion object { - val WIDGET_SIZE = ViewConstants.DEFAULT_WIDGET_SIZE - val TOTAL_XP_WIDGET_SIZE = ViewConstants.TOTAL_XP_WIDGET_SIZE val IMAGE_SIZE = Dimension(25, 23) // Default Theme Colors @@ -142,7 +140,6 @@ class plugin : Plugin() { } override fun Init() { - // Disable Font AA System.setProperty("sun.java2d.opengl", "false") System.setProperty("awt.useSystemAAFontSettings", "off") System.setProperty("swing.aatext", "false") @@ -150,8 +147,6 @@ class plugin : Plugin() { override fun OnLogin() { if (lastLogin != "" && lastLogin != Player.usernameInput.toString()) { - // if we logged in with a new character - // we need to reset the trackers XPTrackerView.xpTrackerView?.let { XPTrackerView.resetXPTracker(it) } } lastLogin = Player.usernameInput.toString() @@ -162,15 +157,12 @@ class plugin : Plugin() { for ((index, entry) in currentEntries.withIndex()) { if (entry.type == MiniMenuType.PLAYER && index == currentEntries.size - 1) { val input = entry.subject - // Trim spaces, clean up tags, and remove the level info val cleanedInput = input - .trim() // Remove any leading/trailing spaces - .replace(Regex(""), "") // Remove color tags - .replace(Regex(""), "") // Remove image tags - .replace(Regex("\\(level: \\d+\\)"), "") // Remove level text e.g. (level: 44) - .trim() // Trim again to remove extra spaces after removing level text - - // Proceed with the full cleaned username + .trim() + .replace(Regex(""), "") + .replace(Regex(""), "") + .replace(Regex("\\(level: \\d+\\)"), "") + .trim() InsertMiniMenuEntry("Lookup", entry.subject, searchHiscore(cleanedInput)) } } @@ -201,7 +193,6 @@ class plugin : Plugin() { frame.revalidate() frame.repaint() - // Rebuild the reflective editor UI on the EDT and in one batch ReflectiveEditorView.addPlugins(ReflectiveEditorView.panel) } pluginsReloaded = true @@ -210,7 +201,6 @@ class plugin : Plugin() { } override fun OnXPUpdate(skillId: Int, xp: Int) { - // Call registered XP update callbacks xpUpdateCallbacks.forEach { callback -> callback.onXPUpdate(skillId, xp) } @@ -223,7 +213,6 @@ class plugin : Plugin() { } if (pluginsReloaded) { - // Rebuild the reflective editor UI on the EDT and in one batch SwingUtilities.invokeLater { ReflectiveEditorView.addPlugins(ReflectiveEditorView.panel) } @@ -237,14 +226,12 @@ class plugin : Plugin() { accumulatedTime += timeDelta if (accumulatedTime >= TICK_INTERVAL) { - // Call registered post client tick callbacks postClientTickCallbacks.forEach { callback -> callback.onPostClientTick() } accumulatedTime = 0L } - // Call registered draw callbacks drawCallbacks.forEach { callback -> callback.onDraw(timeDelta) } @@ -282,25 +269,22 @@ class plugin : Plugin() { } else { moveCanvasToFront() } - altCanvas?.updateGameImage() // Update the game image as needed + altCanvas?.updateGameImage() } override fun Update() { - // Call registered update callbacks updateCallbacks.forEach { callback -> callback.onUpdate() } } override fun OnKillingBlowNPC(npcID: Int, x: Int, z: Int) { - // Call registered killing blow NPC callbacks killingBlowNPCCallbacks.forEach { callback -> callback.onKillingBlowNPC(npcID, x, z) } } private fun allSpritesLoaded() : Boolean { - // Check all skill sprites try{ for (i in 0 until 24) { if(!js5Archive8.isFileReady(getSpriteId(i))){ @@ -481,31 +465,27 @@ class plugin : Plugin() { cardLayout = CardLayout() mainContentPanel = JPanel(cardLayout).apply { - border = BorderFactory.createEmptyBorder(0, 0, 0, 0) // Removes any default border or padding + border = BorderFactory.createEmptyBorder(0, 0, 0, 0) background = VIEW_BACKGROUND_COLOR preferredSize = Dimension(MAIN_CONTENT_WIDTH, frame.height) isOpaque = true } - // Register Views val xpTrackerView = XPTrackerView val hiscoresView = HiscoresView val lootTrackerView = LootTrackerView val reflectiveEditorView = ReflectiveEditorView - // Create views xpTrackerView.createView() hiscoresView.createView() lootTrackerView.createView() reflectiveEditorView.createView() - // Register views views.add(xpTrackerView) views.add(hiscoresView) views.add(lootTrackerView) views.add(reflectiveEditorView) - // Register view functions xpTrackerView.registerFunctions() hiscoresView.registerFunctions() lootTrackerView.registerFunctions() @@ -636,7 +616,6 @@ class plugin : Plugin() { } } - // ImageCanvas with forced size val imageCanvas = ImageCanvas(bufferedImageSprite).apply { background = WIDGET_COLOR setFixedSize(imageSize) @@ -663,7 +642,6 @@ class plugin : Plugin() { add(imageCanvasWrapper, gbc) - // Hover and click behavior val hoverListener = object : MouseAdapter() { override fun mouseEntered(e: MouseEvent?) { background = WIDGET_COLOR.darker() diff --git a/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/GitLabConfig.kt b/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/GitLabConfig.kt index 537bd0a..3aec747 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/GitLabConfig.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/GitLabConfig.kt @@ -5,15 +5,12 @@ package KondoKit.pluginmanager * GitLabPluginFetcher and PluginDownloadManager */ object GitLabConfig { - // GitLab project information - using the ID from PluginFetcher const val GITLAB_PROJECT_ID = "38297322" const val GITLAB_PROJECT_PATH = "2009scape/tools/client-plugins" // Using path from DownloadManager const val GITLAB_BRANCH = "master" - // Debug settings const val DEBUG = true // Set to false to disable debug logging - // API endpoints and URL patterns fun getGitLabApiBaseUrl(): String = "https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID" fun getRepositoryTreeUrl(): String = diff --git a/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/GitLabPluginFetcher.kt b/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/GitLabPluginFetcher.kt index b79dc8d..db8d27c 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/GitLabPluginFetcher.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/GitLabPluginFetcher.kt @@ -13,13 +13,10 @@ import javax.swing.SwingUtilities object GitLabPluginFetcher { private const val TAG = "GitLabPluginFetcher" - // Thread pool for concurrent plugin property fetching private val executorService = Executors.newFixedThreadPool(5) - // Debug logging function private fun debugLog(message: String) = PluginLogger.debug(TAG, message) - // Function to fetch plugins from GitLab fun fetchGitLabPlugins(onComplete: (List) -> Unit) { Thread { val plugins = mutableListOf() @@ -32,12 +29,11 @@ object GitLabPluginFetcher { debugLog("Response length: ${response.length} characters") debugLog("Response preview: ${response.take(200)}...") - // Parse JSON response val treeItems = JsonParser.fromJson(response, Array::class.java) debugLog("Parsed ${treeItems.size} items from JSON") - // Filter for directories (trees) with mode "040000" val pluginDirectories = mutableListOf>() + // Filter for directories (trees) by mode 040000 so we only consider plugin folders for (jsonObject in treeItems) { if (jsonObject["type"].asString == "tree" && jsonObject["mode"].asString == "040000") { val folderId = jsonObject["id"].asString @@ -48,23 +44,21 @@ object GitLabPluginFetcher { } debugLog("Found ${pluginDirectories.size} plugin directories") - // Fetch plugin properties in parallel val pluginFutures = mutableListOf>() for ((folderId, folderPath) in pluginDirectories) { val future = executorService.submit(Callable { try { val pluginProperties = fetchPluginProperties(folderPath) debugLog("Successfully fetched properties for: $folderPath") - GitLabPlugin(folderId, folderPath, pluginProperties, null) + GitLabPlugin(folderId, folderPath, pluginProperties) } catch (e: Exception) { debugLog("Error fetching plugin.properties for $folderPath: ${e.message}") - GitLabPlugin(folderId, folderPath, null, "Error fetching plugin.properties") + GitLabPlugin(folderId, folderPath, null) } }) pluginFutures.add(future) } - // Collect results for (future in pluginFutures) { try { plugins.add(future.get()) @@ -80,14 +74,12 @@ object GitLabPluginFetcher { } debugLog("Completed fetching plugins. Total plugins: ${plugins.size}") - // Update on UI thread SwingUtilities.invokeLater { onComplete(plugins) } }.start() } - // Function to fetch plugin.properties from a specific folder private fun fetchPluginProperties(folderPath: String): PluginProperties { val pluginFilePath = "$folderPath/plugin.properties" val pluginUrl = GitLabConfig.getRawFileUrl(pluginFilePath) @@ -106,7 +98,6 @@ object GitLabPluginFetcher { } } - // Function to parse plugin.properties content private fun parseProperties(content: String): PluginProperties { debugLog("Parsing plugin.properties content") val lines = content.split("\n") diff --git a/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/PluginDownloadManager.kt b/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/PluginDownloadManager.kt index 666af1f..43b388f 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/PluginDownloadManager.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/PluginDownloadManager.kt @@ -1,11 +1,7 @@ package KondoKit.pluginmanager -import KondoKit.pluginmanager.GitLabPlugin import KondoKit.util.HttpFetcher import KondoKit.pluginmanager.GitLabConfig -import KondoKit.views.ReflectiveEditorView -import plugin.PluginRepository -import java.awt.EventQueue import java.io.* import java.net.HttpURLConnection import java.net.URL @@ -21,19 +17,15 @@ object PluginDownloadManager { private const val TAG = "PluginDownloadManager" private const val MAX_CONCURRENT_DOWNLOADS = 3 - // Thread pool for concurrent downloads private val downloadExecutor = Executors.newFixedThreadPool(MAX_CONCURRENT_DOWNLOADS) - // Callback for download progress updates interface DownloadProgressCallback { fun onProgress(pluginName: String, progress: Int) fun onComplete(pluginName: String, success: Boolean, errorMessage: String? = null) } - // Debug logging function private fun debugLog(message: String) = PluginLogger.debug(TAG, message) - // Get download URL for debugging/logging purposes fun getDownloadUrlForLogging(plugin: GitLabPlugin): String { return GitLabConfig.getArchiveUrl(plugin.path) } @@ -47,7 +39,6 @@ object PluginDownloadManager { debugLog("Starting download for plugin: ${plugin.path}") callback.onProgress(plugin.path, 0) - // Download the plugin as a ZIP archive val success = downloadAndExtractPlugin(plugin, callback) if (success) { @@ -77,11 +68,9 @@ object PluginDownloadManager { fun downloadPlugins(plugins: List, callback: (String, Boolean, String?) -> Unit) { debugLog("Starting concurrent download of ${plugins.size} plugins") - // Submit all downloads to the executor for (plugin in plugins) { downloadPlugin(plugin, object : DownloadProgressCallback { override fun onProgress(pluginName: String, progress: Int) { - // We don't need to do anything here for the simple callback } override fun onComplete(pluginName: String, success: Boolean, errorMessage: String?) { @@ -96,7 +85,6 @@ object PluginDownloadManager { */ private fun downloadAndExtractPlugin(plugin: GitLabPlugin, callback: DownloadProgressCallback): Boolean { try { - // Validate plugin path if (plugin.path.isBlank()) { debugLog("Plugin path is blank for plugin: ${plugin.path}") return false @@ -117,7 +105,6 @@ object PluginDownloadManager { for (downloadUrl in downloadUrls) { debugLog("Trying download URL: $downloadUrl") - // Validate URL val url = try { URL(downloadUrl) } catch (e: Exception) { @@ -125,7 +112,6 @@ object PluginDownloadManager { continue } - // Create URL connection val connection = try { HttpFetcher.openGetConnection(url.toString()) } catch (e: Exception) { @@ -137,20 +123,16 @@ object PluginDownloadManager { debugLog("Request headers - User-Agent: ${connection.getRequestProperty("User-Agent")}") debugLog("Request headers - Accept: ${connection.getRequestProperty("Accept")}") - // Get content length for progress tracking val contentLength = connection.contentLength debugLog("Content length: $contentLength bytes for plugin: ${plugin.path}") - // Read response val responseCode = connection.responseCode debugLog("Response code: $responseCode for plugin: ${plugin.path}") - // Log response message val responseMessage = connection.responseMessage debugLog("Response message: $responseMessage for plugin: ${plugin.path}") if (responseCode == HttpURLConnection.HTTP_OK) { - // Check if input stream is available val inputStream = connection.inputStream if (inputStream == null) { debugLog("Input stream is null for plugin: ${plugin.path}") @@ -159,11 +141,9 @@ object PluginDownloadManager { debugLog("Input stream available for plugin: ${plugin.path}") - // Create output directory val pluginsDir = File(rt4.GlobalJsonConfig.instance.pluginsFolder) debugLog("Plugins directory: ${pluginsDir.absolutePath}") - // Validate plugins directory if (!pluginsDir.exists()) { debugLog("Plugins directory does not exist: ${pluginsDir.absolutePath}") if (!pluginsDir.mkdirs()) { @@ -181,13 +161,11 @@ object PluginDownloadManager { val pluginDir = File(pluginsDir, plugin.path) debugLog("Plugin directory: ${pluginDir.absolutePath}") - // Create directory if it doesn't exist if (!pluginDir.exists()) { pluginDir.mkdirs() debugLog("Created plugin directory: ${pluginDir.absolutePath}") } - // Download the ZIP file val tempZipFile = File.createTempFile("plugin_", ".zip") tempZipFile.deleteOnExit() debugLog("Created temp file: ${tempZipFile.absolutePath}") @@ -222,10 +200,8 @@ object PluginDownloadManager { debugLog("Downloaded ${totalBytesRead} bytes to ${tempZipFile.absolutePath}") - // Extract the ZIP file if (extractZipFile(tempZipFile, pluginDir, plugin.path)) { debugLog("Successfully extracted plugin to ${pluginDir.absolutePath}") - // Clean up temp file tempZipFile.delete() return true } else { @@ -270,7 +246,6 @@ object PluginDownloadManager { try { debugLog("Extracting ZIP file: ${zipFile.absolutePath} to ${targetDir.absolutePath}") - // Validate inputs if (!zipFile.exists()) { debugLog("ZIP file does not exist: ${zipFile.absolutePath}") return false @@ -291,8 +266,7 @@ object PluginDownloadManager { debugLog("Processing ZIP entry $entryCount: $entryName") - // Skip the top-level directory in the ZIP (GitLab adds a project-branch-hash directory) - // We want to extract the contents of the plugin directory directly + // Strip the top-level GitLab archive directory so we extract only the plugin contents val relativePath = if (entryName.contains("/")) { entryName.substring(entryName.indexOf("/") + 1) } else { @@ -301,7 +275,6 @@ object PluginDownloadManager { debugLog("Relative path for entry: $relativePath") - // Only extract files that are part of this specific plugin if (relativePath.startsWith(pluginPath) && relativePath != pluginPath) { val fileName = relativePath.substring(pluginPath.length + 1) // +1 for the trailing slash @@ -312,7 +285,6 @@ object PluginDownloadManager { debugLog("Target file path: ${file.absolutePath}") - // Create parent directories if needed val parent = file.parentFile if (parent != null && !parent.exists()) { if (parent.mkdirs()) { @@ -324,7 +296,6 @@ object PluginDownloadManager { } } - // Extract file or directory if (entry!!.isDirectory) { if (!file.exists()) { if (file.mkdirs()) { @@ -336,7 +307,6 @@ object PluginDownloadManager { debugLog("Directory already exists: ${file.absolutePath}") } } else { - // Create file try { FileOutputStream(file).use { fos -> zis.copyTo(fos) diff --git a/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/PluginModels.kt b/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/PluginModels.kt index adf92af..0730430 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/PluginModels.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/PluginModels.kt @@ -3,8 +3,7 @@ package KondoKit.pluginmanager data class GitLabPlugin( val id: String, val path: String, - val pluginProperties: PluginProperties?, - val pluginError: String? + val pluginProperties: PluginProperties? ) data class PluginProperties( diff --git a/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/ReflectiveEditorPlugin.kt b/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/ReflectiveEditorPlugin.kt index 9403ded..1fc505d 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/ReflectiveEditorPlugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/pluginmanager/ReflectiveEditorPlugin.kt @@ -1,8 +1,5 @@ package KondoKit.pluginmanager -import KondoKit.pluginmanager.GitLabPlugin -import KondoKit.pluginmanager.PluginInfoWithStatus -import KondoKit.pluginmanager.PluginProperties import KondoKit.util.FileUtils import KondoKit.util.Helpers import KondoKit.views.ReflectiveEditorView @@ -17,22 +14,18 @@ import javax.swing.* class ReflectiveEditorPlugin : Plugin() { - // Fields that were previously in ReflectiveEditorView private var gitLabPlugins: List = listOf() private var pluginStatuses: List = 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 = gitLabPlugins fun getPluginStatuses(): List = pluginStatuses @@ -41,13 +34,10 @@ class ReflectiveEditorPlugin : Plugin() { val loadedPluginNames = getLoadedPluginNames() val statuses = mutableListOf() - // 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 @@ -62,13 +52,11 @@ class ReflectiveEditorPlugin : Plugin() { 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 @@ -82,10 +70,8 @@ class ReflectiveEditorPlugin : Plugin() { 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, @@ -99,9 +85,7 @@ class ReflectiveEditorPlugin : Plugin() { 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, @@ -120,12 +104,10 @@ class ReflectiveEditorPlugin : Plugin() { pluginStatuses = statuses } - // Helper method to get currently loaded plugin names private fun getLoadedPluginNames(): Set { val loadedPluginNames = mutableSetOf() try { - // Get loaded plugins val loadedPluginsField = PluginRepository::class.java.getDeclaredField("loadedPlugins") loadedPluginsField.isAccessible = true val loadedPlugins = loadedPluginsField.get(null) as HashMap<*, *> @@ -141,7 +123,6 @@ class ReflectiveEditorPlugin : Plugin() { return loadedPluginNames } - // Helper method to parse plugin.properties content private fun parsePluginProperties(content: String): PluginProperties { var author = "Unknown" var version = "Unknown" @@ -171,7 +152,6 @@ class ReflectiveEditorPlugin : Plugin() { return PluginProperties(author, version, description) } - // Helper method to get disabled plugin names and their versions private fun getDisabledPluginInfo(): Map { val disabledPluginInfo = mutableMapOf() val disabledDir = File(pluginsDirectory, "disabled") @@ -196,7 +176,6 @@ class ReflectiveEditorPlugin : Plugin() { return disabledPluginInfo } - // Helper method to handle duplicate plugins (loaded and disabled) private fun handleDuplicatePlugins(loadedPluginNames: Set, disabledPluginInfo: Map) { var needsReload = false for (pluginName in loadedPluginNames) { @@ -221,7 +200,6 @@ class ReflectiveEditorPlugin : Plugin() { } } - // Helper method to delete a plugin fun deletePlugin(pluginName: String, isDisabled: Boolean, mainPanel: Component) { try { val pluginDir = if (isDisabled) { @@ -231,16 +209,13 @@ class ReflectiveEditorPlugin : Plugin() { } if (pluginDir.exists() && pluginDir.isDirectory) { - // Recursively delete the directory if (FileUtils.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) } @@ -256,33 +231,26 @@ class ReflectiveEditorPlugin : Plugin() { } } - // 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) } @@ -295,26 +263,19 @@ class ReflectiveEditorPlugin : Plugin() { } } - // 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() @@ -322,10 +283,8 @@ class ReflectiveEditorPlugin : Plugin() { 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() @@ -334,20 +293,17 @@ class ReflectiveEditorPlugin : Plugin() { 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() @@ -357,7 +313,6 @@ class ReflectiveEditorPlugin : Plugin() { } 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() @@ -366,7 +321,6 @@ class ReflectiveEditorPlugin : Plugin() { } } - // 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 @@ -374,15 +328,12 @@ class ReflectiveEditorPlugin : Plugin() { 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) { @@ -390,7 +341,6 @@ class ReflectiveEditorPlugin : Plugin() { return } - // Update plugin status to show downloading val updatedStatuses = pluginStatuses.map { if (it.name == pluginStatus.name) { it.copy(isDownloading = true, downloadProgress = 0) @@ -400,15 +350,12 @@ class ReflectiveEditorPlugin : Plugin() { } 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) @@ -418,14 +365,12 @@ class ReflectiveEditorPlugin : Plugin() { } 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) @@ -435,7 +380,6 @@ class ReflectiveEditorPlugin : Plugin() { } 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 @@ -444,7 +388,6 @@ class ReflectiveEditorPlugin : Plugin() { Helpers.showToast(mainPanel, "Failed to download plugin: ${errorMessage ?: "Unknown error"}", JOptionPane.ERROR_MESSAGE) } - // Refresh UI SwingUtilities.invokeLater { ReflectiveEditorView.addPlugins(ReflectiveEditorView.panel) } @@ -452,13 +395,10 @@ class ReflectiveEditorPlugin : Plugin() { }) } - // 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 } diff --git a/plugin-playground/src/main/kotlin/KondoKit/ui/ViewConstants.kt b/plugin-playground/src/main/kotlin/KondoKit/ui/ViewConstants.kt index 49e5162..276b730 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/ui/ViewConstants.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/ui/ViewConstants.kt @@ -1,6 +1,5 @@ package KondoKit.ui -import java.awt.Color import java.awt.Dimension import java.awt.Font @@ -34,12 +33,6 @@ object ViewConstants { val PROGRESS_BAR_SIZE = Dimension(220, 16) val TOGGLE_SWITCH_SIZE = Dimension(32, 20) - val COLOR_WHITE = Color.WHITE - val COLOR_BLACK = Color.BLACK - val COLOR_DARK_GRAY = Color.DARK_GRAY - val COLOR_RED = Color.RED - val COLOR_GRAY = Color.GRAY - val SKILL_DISPLAY_ORDER = arrayOf(0, 3, 14, 2, 16, 13, 1, 15, 10, 4, 17, 7, 5, 12, 11, 6, 9, 8, 20, 18, 19, 22, 21, 23) const val COMBAT_LVL_SPRITE = 168 diff --git a/plugin-playground/src/main/kotlin/KondoKit/ui/components/IconComponent.kt b/plugin-playground/src/main/kotlin/KondoKit/ui/components/IconComponent.kt index 2e4aee5..8518bf0 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/ui/components/IconComponent.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/ui/components/IconComponent.kt @@ -4,8 +4,6 @@ import KondoKit.util.ImageCanvas import KondoKit.util.SpriteToBufferedImage import KondoKit.util.setFixedSize import KondoKit.plugin.Companion.WIDGET_COLOR -import KondoKit.plugin.Companion.primaryColor -import KondoKit.plugin.Companion.secondaryColor import plugin.api.API import java.awt.BorderLayout import java.awt.Color diff --git a/plugin-playground/src/main/kotlin/KondoKit/ui/components/ProgressBar.kt b/plugin-playground/src/main/kotlin/KondoKit/ui/components/ProgressBar.kt index 430f485..ba3e078 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/ui/components/ProgressBar.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/ui/components/ProgressBar.kt @@ -22,38 +22,32 @@ class ProgressBar( override fun paint(g: Graphics) { super.paint(g) - // Draw the filled part of the progress bar g.color = barColor val width = (progress * this.width / 100).toInt() g.fillRect(0, 0, width, this.height) - // Draw the unfilled part of the progress bar g.color = PROGRESS_BAR_FILL g.fillRect(width, 0, this.width - width, this.height) - // Variables for text position val textY = this.height / 2 + 6 - // Draw the current level on the far left drawTextWithShadow(g, "Lvl. $currentLevel", 5, textY, secondaryColor) - // Draw the percentage in the middle val percentageText = String.format("%.2f%%", progress) val percentageWidth = g.fontMetrics.stringWidth(percentageText) drawTextWithShadow(g, percentageText, (this.width - percentageWidth) / 2, textY, secondaryColor) - // Draw the next level on the far right val nextLevelText = "Lvl. $nextLevel" val nextLevelWidth = g.fontMetrics.stringWidth(nextLevelText) drawTextWithShadow(g, nextLevelText, this.width - nextLevelWidth - 5, textY, secondaryColor) } override fun getPreferredSize(): Dimension { - return ViewConstants.PROGRESS_BAR_SIZE // Force the height to 16px, width can be anything appropriate + return ViewConstants.PROGRESS_BAR_SIZE } override fun getMinimumSize(): Dimension { - return ViewConstants.PROGRESS_BAR_SIZE // Force the minimum height to 16px, width can be smaller + return ViewConstants.PROGRESS_BAR_SIZE } fun updateProgress(newProgress: Double, currentLevel: Int, nextLevel: Int, isVisible : Boolean) { @@ -64,13 +58,10 @@ class ProgressBar( repaint() } - // Helper function to draw text with a shadow effect private fun drawTextWithShadow(g: Graphics, text: String, x: Int, y: Int, textColor: Color) { - // Draw shadow (black text with -1 x and -1 y offset) g.color = Color(0, 0, 0) g.drawString(text, x + 1, y + 1) - // Draw actual text on top g.color = textColor g.drawString(text, x, y) } diff --git a/plugin-playground/src/main/kotlin/KondoKit/ui/components/ToggleSwitch.kt b/plugin-playground/src/main/kotlin/KondoKit/ui/components/ToggleSwitch.kt index 5371dca..e5c090b 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/ui/components/ToggleSwitch.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/ui/components/ToggleSwitch.kt @@ -34,7 +34,7 @@ class ToggleSwitch : JPanel() { }) cursor = Cursor(Cursor.HAND_CURSOR) setFixedSize(ViewConstants.TOGGLE_SWITCH_SIZE) - isOpaque = false // Make the panel background transparent + isOpaque = false } override fun paint(gr: Graphics) { @@ -48,21 +48,18 @@ class ToggleSwitch : JPanel() { g?.setRenderingHints(rh) } - // Clear the buffer with transparent background g?.color = Color(0, 0, 0, 0) g?.fillRect(0, 0, width, height) - // Draw the track with circular ends (rounded rectangle) val trackHeight = height - 2 val trackWidth = width - 2 - val trackArc = trackHeight // Makes it fully rounded at the ends + val trackArc = trackHeight g?.color = if (activated) activeSwitch else switchColor g?.fillRoundRect(1, 1, trackWidth, trackHeight, trackArc, trackArc) g?.color = borderColor g?.drawRoundRect(1, 1, trackWidth, trackHeight, trackArc, trackArc) - // Draw the thumb (circular button) val thumbDiameter = trackHeight - 4 val thumbX = if (activated) { width - thumbDiameter - 3 // Right side when activated diff --git a/plugin-playground/src/main/kotlin/KondoKit/util/GEPriceService.kt b/plugin-playground/src/main/kotlin/KondoKit/util/GEPriceService.kt index 72c2656..892e77c 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/util/GEPriceService.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/util/GEPriceService.kt @@ -1,7 +1,5 @@ package KondoKit.util -import KondoKit.util.HttpFetcher - /** * Shared loader for GE price JSON from remote or bundled sources. */ diff --git a/plugin-playground/src/main/kotlin/KondoKit/views/HiscoresView.kt b/plugin-playground/src/main/kotlin/KondoKit/views/HiscoresView.kt index 505db54..2fa70ea 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/views/HiscoresView.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/views/HiscoresView.kt @@ -44,7 +44,6 @@ object HiscoresView : View { } override fun registerFunctions() { - // Hiscores functions are handled within the view itself } fun createHiscoreSearchView() { @@ -72,7 +71,7 @@ object HiscoresView : View { widgetHeight = ViewConstants.FILTER_PANEL_SIZE.height, addDefaultPadding = false ).apply { - layout = GridBagLayout() // This will center the JLabel both vertically and horizontally + layout = GridBagLayout() background = TOOLTIP_BACKGROUND.darker() name = "playerNameLabel" } @@ -214,17 +213,13 @@ object HiscoresView : View { data class Skill( val id: String, - val dynamic: String, - val experience: String, val static: String ) - // Function to search for players in hiscores, extracted from the old inner class fun searchPlayerForHiscores(username: String, hiscoresPanel: JPanel) { if(username.isEmpty() || username.length < 3) { - // Skip on no value return } @@ -268,12 +263,12 @@ object HiscoresView : View { private fun updateHiscoresViewStandalone(hiscoresPanel: JPanel, data: HiscoresResponse?, username: String) { val playerNameLabel = findComponentByNameStandalone(hiscoresPanel, "playerNameLabel") as? JPanel - playerNameLabel?.removeAll() // Clear previous components + playerNameLabel?.removeAll() var nameLabel = LabelComponent().apply { updateHtmlText(username, secondaryColor, "", primaryColor) font = ViewConstants.FONT_ARIAL_BOLD_12 foreground = POPUP_FOREGROUND - border = BorderFactory.createEmptyBorder(0, 6, 0, 0) // Top, Left, Bottom, Right padding + border = BorderFactory.createEmptyBorder(0, 6, 0, 0) horizontalAlignment = JLabel.CENTER } playerNameLabel?.add(nameLabel) @@ -304,7 +299,7 @@ object HiscoresView : View { updateHtmlText(username, secondaryColor, " (${exp_multiplier}x)", primaryColor) font = ViewConstants.FONT_ARIAL_BOLD_12 foreground = POPUP_FOREGROUND - border = BorderFactory.createEmptyBorder(0, 6, 0, 0) // Top, Left, Bottom, Right padding + border = BorderFactory.createEmptyBorder(0, 6, 0, 0) horizontalAlignment = JLabel.CENTER } @@ -314,7 +309,6 @@ object HiscoresView : View { playerNameLabel?.revalidate() playerNameLabel?.repaint() - // Update skill labels data.skills.forEachIndexed { index, skill -> val labelName = "skillLabel_$index" val numberLabel = findComponentByNameStandalone(hiscoresPanel, labelName) as? JLabel diff --git a/plugin-playground/src/main/kotlin/KondoKit/views/LootTrackerView.kt b/plugin-playground/src/main/kotlin/KondoKit/views/LootTrackerView.kt index 11239c3..cd45de8 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/views/LootTrackerView.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/views/LootTrackerView.kt @@ -19,7 +19,6 @@ import KondoKit.ui.components.LabelComponent import KondoKit.ui.components.WidgetPanel import KondoKit.plugin.Companion.TITLE_BAR_COLOR import KondoKit.plugin.Companion.TOOLTIP_BACKGROUND -import KondoKit.plugin.Companion.TOTAL_XP_WIDGET_SIZE import KondoKit.plugin.Companion.WIDGET_COLOR import KondoKit.plugin.Companion.primaryColor import KondoKit.plugin.Companion.registerDrawAction @@ -30,7 +29,6 @@ import plugin.api.API import rt4.* import java.awt.* import java.awt.Component -import java.awt.Font import java.awt.event.MouseAdapter import java.awt.event.MouseEvent import java.awt.image.BufferedImage @@ -63,7 +61,6 @@ object LootTrackerView : View, OnPostClientTickCallback, OnKillingBlowNPCCallbac } override fun registerFunctions() { - // Register callbacks with the plugin KondoKit.plugin.registerPostClientTickCallback(this) KondoKit.plugin.registerKillingBlowNPCCallback(this) } @@ -184,7 +181,6 @@ object LootTrackerView : View, OnPostClientTickCallback, OnKillingBlowNPCCallbac ?.let { updateItemPanelIcon(it, drop.id, newQuantity) } ?: addNewItemToPanel(lootPanel, drop, newQuantity) - // Recalculate lootPanel size based on the number of unique items. val totalItems = lootItemPanels[npcName]?.size ?: 0 val rowsNeeded = ceil(totalItems / 6.0).toInt() val lootPanelHeight = rowsNeeded * (40) @@ -208,7 +204,6 @@ object LootTrackerView : View, OnPostClientTickCallback, OnKillingBlowNPCCallbac private fun createItemPanel(itemId: Int, quantity: Int): JPanel { val bufferedImageSprite = getBufferedImageFromSprite(API.GetObjSprite(itemId, quantity, true, 1, 3153952)) - // Create the panel for the item val itemPanel = FixedSizePanel(Dimension(36, 32)).apply { background = WIDGET_COLOR @@ -217,21 +212,16 @@ object LootTrackerView : View, OnPostClientTickCallback, OnKillingBlowNPCCallbac background = WIDGET_COLOR } - // Add the imageCanvas to the panel add(imageCanvas, BorderLayout.CENTER) - // Put the itemId as a property for reference putClientProperty("itemId", itemId) - // Add mouse listener for custom hover text imageCanvas.addMouseListener(object : MouseAdapter() { override fun mouseEntered(e: MouseEvent) { - // Show custom tooltip when the mouse enters the component showCustomToolTip(e.point, itemId,quantity,imageCanvas) } override fun mouseExited(e: MouseEvent) { - // Hide tooltip when mouse exits hideCustomToolTip() } }) @@ -240,7 +230,6 @@ object LootTrackerView : View, OnPostClientTickCallback, OnKillingBlowNPCCallbac return itemPanel } - // Function to show the custom tooltip fun showCustomToolTip(location: Point, itemId: Int, quantity: Int, parentComponent: ImageCanvas) { val itemDef = ObjTypeList.get(itemId) val gePricePerItem = gePriceMap[itemDef.id.toString()]?.toInt() ?: 0 @@ -269,13 +258,11 @@ object LootTrackerView : View, OnPostClientTickCallback, OnKillingBlowNPCCallbac } } - // Calculate the tooltip location relative to the parent component val screenLocation = parentComponent.locationOnScreen customToolTipWindow!!.setLocation(screenLocation.x + location.x, screenLocation.y + location.y + 20) customToolTipWindow!!.isVisible = true } - // Function to hide the custom tooltip fun hideCustomToolTip() { customToolTipWindow?.isVisible = false customToolTipWindow = null // Nullify the global instance @@ -427,7 +414,6 @@ object LootTrackerView : View, OnPostClientTickCallback, OnKillingBlowNPCCallbac labelPanel.add(countLabel, BorderLayout.WEST) labelPanel.add(valueLabel, BorderLayout.EAST) - // Panel to hold loot items, using GridLayout to manage rows and columns. val lootPanel = JPanel().apply { background = WIDGET_COLOR border = BorderFactory.createLineBorder(WIDGET_COLOR, 5) @@ -446,7 +432,6 @@ object LootTrackerView : View, OnPostClientTickCallback, OnKillingBlowNPCCallbac } private fun removeLootFrameMenu(toRemove: JPanel, npcName: String): JPopupMenu { - // Create a popup menu val popupMenu = PopupMenuComponent() popupMenu.addMenuItem("Remove") { lootItemPanels[npcName]?.clear() @@ -457,8 +442,6 @@ object LootTrackerView : View, OnPostClientTickCallback, OnKillingBlowNPCCallbac if (toRemoveIndex >= 0 && toRemoveIndex < components.size - 1) { val nextComponent = components[toRemoveIndex + 1] if (nextComponent is Box.Filler) { - // Nasty way to remove the Box.createVerticalStrut(8) after - // the lootpanel. parent.remove(nextComponent) } } @@ -472,7 +455,6 @@ object LootTrackerView : View, OnPostClientTickCallback, OnKillingBlowNPCCallbac private fun resetLootTrackerMenu(): JPopupMenu { - // Create a popup menu val popupMenu = PopupMenuComponent() popupMenu.addMenuItem("Reset Loot Tracker") { diff --git a/plugin-playground/src/main/kotlin/KondoKit/views/ReflectiveEditorView.kt b/plugin-playground/src/main/kotlin/KondoKit/views/ReflectiveEditorView.kt index 9715597..452c9fa 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/views/ReflectiveEditorView.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/views/ReflectiveEditorView.kt @@ -3,16 +3,11 @@ package KondoKit.views import KondoKit.pluginmanager.ReflectiveEditorPlugin import KondoKit.util.attachPopupMenu import KondoKit.ui.components.* -import KondoKit.pluginmanager.GitLabPlugin import KondoKit.pluginmanager.PluginInfoWithStatus -import KondoKit.pluginmanager.PluginProperties -import KondoKit.plugin.Companion.TOOLTIP_BACKGROUND import KondoKit.plugin.Companion.VIEW_BACKGROUND_COLOR import KondoKit.plugin.Companion.WIDGET_COLOR import KondoKit.plugin.Companion.WRENCH_ICON import KondoKit.plugin.Companion.secondaryColor -import KondoKit.pluginmanager.GitLabPluginFetcher -import KondoKit.pluginmanager.PluginDownloadManager import KondoKit.util.setFixedSize import KondoKit.ui.BaseView import KondoKit.ui.View @@ -22,7 +17,6 @@ import KondoKit.views.ViewLayoutHelpers.createSearchFieldSection import plugin.Plugin import plugin.PluginInfo import plugin.PluginRepository -import rt4.GlobalJsonConfig import java.awt.* import java.io.File import java.util.* @@ -47,18 +41,15 @@ object ReflectiveEditorView : View { private var searchField: SearchField? = null - // Helper function to check if a plugin is the KondoKit plugin private fun isKondoKit(pluginName: String): Boolean { return pluginName == "KondoKit" } - // Card layout for switching between views within the reflective editor view private lateinit var cardLayout: CardLayout private lateinit var mainPanel: JPanel private var currentPluginInfo: PluginInfo? = null private var currentPlugin: Plugin? = null - // Search text for filtering plugins private var pluginSearchText: String = "" private var searchFieldWrapper: JPanel? = null private var pluginListContentPanel: JPanel? = null @@ -70,7 +61,6 @@ object ReflectiveEditorView : View { get() = reflectiveEditorView ?: JPanel() override fun createView() { - // Initialize the plugin reflectiveEditorPlugin.Init() createReflectiveEditorView() } @@ -98,8 +88,6 @@ object ReflectiveEditorView : View { reflectiveEditorView = mainPanel cardLayout.show(mainPanel, PLUGIN_LIST_VIEW) - - // Plugin initialization is handled by the plugin class, gitLabPlugins will be fetched automatically } private fun createPluginListView(): JPanel { @@ -152,16 +140,14 @@ object ReflectiveEditorView : View { val contentPanel = pluginListContentPanel ?: return val treeLock = contentPanel.treeLock - synchronized(treeLock) { + synchronized(treeLock) { contentPanel.removeAll() try { - // Get loaded plugins val loadedPluginsField = PluginRepository::class.java.getDeclaredField("loadedPlugins") loadedPluginsField.isAccessible = true val loadedPlugins = loadedPluginsField.get(null) as HashMap<*, *> - // Separate plugins with and without exposed attributes val pluginsWithExposed = mutableListOf>() val pluginsWithoutExposed = mutableListOf>() @@ -172,7 +158,6 @@ object ReflectiveEditorView : View { } } - // Apply search filter val pluginName = plugin.javaClass.`package`.name if (pluginSearchText.isBlank() || pluginName.contains(pluginSearchText, ignoreCase = true)) { if (exposedFields.isNotEmpty()) { @@ -278,31 +263,26 @@ object ReflectiveEditorView : View { layout = BorderLayout() } - // Plugin name and version (using package name as in original implementation) val packageName = plugin.javaClass.`package`.name val nameLabel = JLabel(packageName) nameLabel.foreground = secondaryColor nameLabel.font = ViewConstants.FONT_RUNESCAPE_SMALL_PLAIN_16 - // Check if plugin has exposed attributes val exposedFields = plugin.javaClass.declaredFields.filter { field -> field.annotations.any { annotation -> annotation.annotationClass.simpleName == "Exposed" } } - // Edit button (only show if plugin has exposed attributes) val editButton = exposedFields.takeIf { it.isNotEmpty() }?.let { UiStyler.button(text = "Edit") { showPluginDetails(pluginInfo, plugin) } } - // Plugin toggle switch (iOS style) - skip for KondoKit since it should always be on val toggleSwitch = if (!isKondoKit(packageName)) { createToggleSwitch(plugin, pluginInfo) } else { - // Create a placeholder component that takes the same space but is invisible val placeholder = JPanel() placeholder.background = WIDGET_COLOR placeholder.setFixedSize(ViewConstants.TOGGLE_PLACEHOLDER_SIZE) @@ -339,25 +319,21 @@ object ReflectiveEditorView : View { layout = BorderLayout() } - // Plugin name val nameLabel = JLabel(pluginName) nameLabel.foreground = secondaryColor nameLabel.font = ViewConstants.FONT_RUNESCAPE_SMALL_PLAIN_16 - // Plugin toggle switch (iOS style) - initially off for disabled plugins val toggleSwitch = ToggleSwitch() toggleSwitch.setActivated(false) toggleSwitch.onToggleListener = { activated -> if (activated) { reflectiveEditorPlugin.enablePlugin(pluginName, mainPanel ?: JPanel()) } - // If trying to disable an already disabled plugin, reset the toggle else { toggleSwitch.setActivated(false) } } - // Layout val infoPanel = JPanel(BorderLayout()) infoPanel.background = WIDGET_COLOR infoPanel.add(nameLabel, BorderLayout.WEST) @@ -369,7 +345,6 @@ object ReflectiveEditorView : View { panel.add(infoPanel, BorderLayout.CENTER) panel.add(controlsPanel, BorderLayout.EAST) - // Add right-click context menu (except for KondoKit itself) if (!isKondoKit(pluginName)) { val popupMenu = createPluginContextMenu(null, null, pluginName, true) panel.attachPopupMenu(popupMenu) @@ -383,15 +358,11 @@ object ReflectiveEditorView : View { layout = BorderLayout() } - // Plugin name val nameLabel = JLabel(pluginStatus.name) nameLabel.foreground = secondaryColor nameLabel.font = ViewConstants.FONT_RUNESCAPE_SMALL_PLAIN_16 - // Action button based on plugin status val actionButton = UiStyler.button() - - // Progress bar for downloads val progressBar = JProgressBar(0, 100) progressBar.isStringPainted = true progressBar.isVisible = false @@ -405,7 +376,6 @@ object ReflectiveEditorView : View { if (pluginStatus.needsUpdate) { actionButton.text = "Update" actionButton.addActionListener { - // Start downloading the plugin to update it startPluginDownload(pluginStatus) } } else { @@ -415,17 +385,14 @@ object ReflectiveEditorView : View { } else { actionButton.text = "Download" actionButton.addActionListener { - // Start downloading the plugin startPluginDownload(pluginStatus) } } - // Plugin toggle switch (iOS style) val toggleSwitch = ToggleSwitch() - + // Skip the toggle switch for KondoKit since it should always be enabled if (isKondoKit(pluginStatus.name)) { - // Hide the toggle switch for KondoKit toggleSwitch.isVisible = false } else { toggleSwitch.setActivated(pluginStatus.isInstalled && !pluginStatus.needsUpdate) @@ -433,7 +400,6 @@ object ReflectiveEditorView : View { if (pluginStatus.isInstalled && !pluginStatus.needsUpdate) { toggleSwitch.onToggleListener = { activated -> - // 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<*, *> @@ -452,21 +418,16 @@ object ReflectiveEditorView : View { 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() @@ -474,33 +435,26 @@ object ReflectiveEditorView : View { 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 + + reflectiveEditorPlugin.setReloadPlugins(true) // Schedule plugin reload to avoid crashes + 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) + toggleSwitch.setActivated(!activated) // Reset toggle to previous state on failure } } } } } else { - // Hide the toggle switch for non-installed plugins toggleSwitch.isVisible = false } } @@ -581,11 +535,8 @@ object ReflectiveEditorView : View { private fun createToggleSwitch(plugin: Plugin, pluginInfo: PluginInfo): ToggleSwitch { val toggleSwitch = ToggleSwitch() - - // Set initial state + toggleSwitch.setActivated(reflectiveEditorPlugin.isPluginEnabled(plugin, pluginInfo)) - - // Add toggle listener toggleSwitch.onToggleListener = { activated -> reflectiveEditorPlugin.togglePlugin(plugin, pluginInfo, toggleSwitch, activated, mainPanel ?: JPanel()) } @@ -594,7 +545,6 @@ object ReflectiveEditorView : View { } 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(".") @@ -606,18 +556,15 @@ object ReflectiveEditorView : View { searchFieldWrapper?.isVisible = false - // Remove the existing detail view if it exists val existingDetailView = mainPanel.components.find { it.name == PLUGIN_DETAIL_VIEW } if (existingDetailView != null) { mainPanel.remove(existingDetailView) } - // Create a new detail view val detailView = BaseView(PLUGIN_DETAIL_VIEW) detailView.layout = BorderLayout() detailView.background = VIEW_BACKGROUND_COLOR - // Header with back button val packageName = plugin.javaClass.`package`.name val headerPanel = ViewHeader("$packageName v${pluginInfo.version}", 40).apply { @@ -625,7 +572,6 @@ object ReflectiveEditorView : View { } val backButton = ButtonPanel(FlowLayout.LEFT).addButton("Back") { - // Reset scroll position to top when returning to the list view SwingUtilities.invokeLater { // Find the ScrollablePanel in the plugin list view and reset its scroll position val listView = mainPanel.components.find { it.name == PLUGIN_LIST_VIEW } @@ -640,7 +586,6 @@ object ReflectiveEditorView : View { headerPanel.add(backButton, BorderLayout.WEST) - // Content panel for settings val contentPanel = JPanel() contentPanel.layout = BoxLayout(contentPanel, BoxLayout.Y_AXIS) contentPanel.background = VIEW_BACKGROUND_COLOR @@ -693,28 +638,22 @@ object ReflectiveEditorView : View { contentPanel.add(infoPanel) contentPanel.add(Box.createVerticalStrut(10)) - // Add exposed fields addPluginSettings(contentPanel, plugin) - // Wrap the content panel in a ScrollablePanel for custom scrolling val scrollablePanel = ScrollablePanel(contentPanel) - // Reset scroll position to top when entering the edit page SwingUtilities.invokeLater { resetScrollablePanel(scrollablePanel) } detailView.add(headerPanel, BorderLayout.NORTH) detailView.add(scrollablePanel, BorderLayout.CENTER) - - // Add the new detail view to the main panel + mainPanel.add(detailView, PLUGIN_DETAIL_VIEW) - - // Revalidate and repaint the main panel + mainPanel.revalidate() mainPanel.repaint() - - // Show the detail view + cardLayout.show(mainPanel, PLUGIN_DETAIL_VIEW) } @@ -773,7 +712,6 @@ object ReflectiveEditorView : View { mainPanel.repaint() } - // Helper method to find and reset ScrollablePanel components within a container private fun findAndResetScrollablePanel(container: Component) { if (container is ScrollablePanel) { resetScrollablePanel(container) @@ -783,17 +721,14 @@ object ReflectiveEditorView : View { } } } - - // Method to start downloading a plugin + private fun startPluginDownload(pluginStatus: PluginInfoWithStatus) { reflectiveEditorPlugin.startPluginDownload(pluginStatus, mainPanel ?: JPanel()) } - - // Helper method to create context menu for plugins + private fun createPluginContextMenu(plugin: Plugin?, pluginInfo: PluginInfo?, pluginName: String, isDisabled: Boolean): JPopupMenu { val popupMenu = PopupMenuComponent() - // Add "Delete" menu item popupMenu.addMenuItem("Delete Plugin") { deletePlugin(pluginName, isDisabled) } @@ -801,15 +736,11 @@ object ReflectiveEditorView : View { return popupMenu } - // Helper method to delete a plugin private fun deletePlugin(pluginName: String, isDisabled: Boolean) { reflectiveEditorPlugin.deletePlugin(pluginName, isDisabled, mainPanel ?: JPanel()) } - // Helper method to reset a ScrollablePanel to the top private fun resetScrollablePanel(scrollablePanel: ScrollablePanel) { - // Access the content panel and reset its position - // Since we can't directly access the private fields, we'll use reflection try { val contentField = ScrollablePanel::class.java.getDeclaredField("content") contentField.isAccessible = true diff --git a/plugin-playground/src/main/kotlin/KondoKit/views/XPTrackerView.kt b/plugin-playground/src/main/kotlin/KondoKit/views/XPTrackerView.kt index cced344..eb4ff7c 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/views/XPTrackerView.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/views/XPTrackerView.kt @@ -21,9 +21,7 @@ import KondoKit.ui.components.WidgetPanel import KondoKit.ui.components.XPWidget import KondoKit.plugin.Companion.IMAGE_SIZE import KondoKit.plugin.Companion.LVL_ICON -import KondoKit.plugin.Companion.TOTAL_XP_WIDGET_SIZE import KondoKit.plugin.Companion.WIDGET_COLOR -import KondoKit.plugin.Companion.WIDGET_SIZE import KondoKit.plugin import KondoKit.plugin.Companion.playerXPMultiplier import KondoKit.plugin.Companion.primaryColor @@ -121,7 +119,6 @@ object XPTrackerView : View, OnUpdateCallback, OnXPUpdateCallback { } override fun registerFunctions() { - // Register callbacks with the plugin plugin.registerUpdateCallback(this) plugin.registerXPUpdateCallback(this) } @@ -165,7 +162,6 @@ object XPTrackerView : View, OnUpdateCallback, OnXPUpdateCallback { xpWidget = createXPWidget(skillId, previousXpSnapshot) xpWidgets[skillId] = xpWidget - // Create new widget val wrapped = wrappedWidget(xpWidget.container, padding = 0, innerPadding = 6) val popupMenu = removeXPWidgetMenu(wrapped, skillId) wrapped.attachPopupMenu(popupMenu, includeChildren = true) @@ -228,7 +224,6 @@ object XPTrackerView : View, OnUpdateCallback, OnXPUpdateCallback { val formattedXp = formatNumber(xpWidget.totalXpGained) xpWidget.xpGainedLabel.text = formatHtmlLabelText("XP Gained: ", primaryColor, formattedXp, secondaryColor) - // Update the progress bar with current level, progress, and next level xpWidget.progressBar.updateProgress(progress, currentLevel, if (currentLevel < 99) currentLevel + 1 else 99, focusedView == VIEW_NAME) xpWidget.previousXp = xp