diff --git a/druid/editor_scripts/core/asset_store.lua b/druid/editor_scripts/core/asset_store.lua index 79e4294..c36e1d9 100644 --- a/druid/editor_scripts/core/asset_store.lua +++ b/druid/editor_scripts/core/asset_store.lua @@ -134,7 +134,7 @@ function M.open_asset_store() end local dialog_component = editor.ui.component(function(props) - editor.prefs.set("druid.asset_install_folder", "./widget") + editor.prefs.set("druid.asset_install_folder", "/widget") -- State management local items, set_items = editor.ui.use_state(initial_items) local loading, set_loading = editor.ui.use_state(initial_loading) diff --git a/druid/editor_scripts/core/installer.lua b/druid/editor_scripts/core/installer.lua index 5ba50fe..dcf1d91 100644 --- a/druid/editor_scripts/core/installer.lua +++ b/druid/editor_scripts/core/installer.lua @@ -1,10 +1,11 @@ local base64 = require("druid.editor_scripts.core.base64") +local path_replacer = require("druid.editor_scripts.core.path_replacer") --- Module for handling widget installation from zip files --- Downloads zip files and extracts them to the specified folder local M = {} -local DEFAULT_INSTALL_FOLDER = "./widget" +local DEFAULT_INSTALL_FOLDER = "/widget" ---@class druid.core.item_info ---@field id string @@ -57,7 +58,7 @@ function M.install_widget(item, install_folder) end - local zip_file_path = install_folder .. "/" .. filename + local zip_file_path = "." .. install_folder .. "/" .. filename local zip_file = io.open(zip_file_path, "wb") if not zip_file then return false, "Failed to open zip file: " .. zip_file_path @@ -68,14 +69,23 @@ function M.install_widget(item, install_folder) print("Zip written to file: " .. zip_file_path) -- Unzip the zip file - local folder_name = item.id .. "-" .. item.version - zip.unpack(zip_file_path, install_folder .. "/" .. folder_name) + local folder_path = "." .. install_folder .. "/" .. item.id + + zip.unpack(zip_file_path, folder_path) print("Widget unpacked successfully") -- Remove the zip file os.remove(zip_file_path) print("Zip file removed successfully") + -- Process paths within the extracted widget + local files_in_folder = path_replacer.get_all_files(folder_path) + pprint(files_in_folder) + + --if not path_replacer.process_widget_paths(install_folder .. "/" .. folder_name, new_base_path) then + -- return false, "Failed to process widget paths" + --end + return true, "Widget installed successfully" end diff --git a/druid/editor_scripts/core/path_replacer.lua b/druid/editor_scripts/core/path_replacer.lua new file mode 100644 index 0000000..f38505a --- /dev/null +++ b/druid/editor_scripts/core/path_replacer.lua @@ -0,0 +1,22 @@ +--- Module for replacing paths in extracted widget files +--- Handles updating require statements and file paths to match the installation location + +local M = {} + + +---Recursively get all files in a directory +---@param dir_path string - Directory path to scan +---@param extension string|nil - Optional file extension filter (e.g., ".lua") +---@return string[] - List of file paths +function M.get_all_files(dir_path, extension) + local attributes = editor.resource_attributes(dir_path) + local files = io.popen("ls -R " .. dir_path) + for line in files:lines() do + print(line) + end + pprint(files) + return files +end + + +return M diff --git a/druid/editor_scripts/core/ui_components.lua b/druid/editor_scripts/core/ui_components.lua index 22b23c5..f6aa6ae 100644 --- a/druid/editor_scripts/core/ui_components.lua +++ b/druid/editor_scripts/core/ui_components.lua @@ -9,20 +9,20 @@ local M = {} ---@param on_change function - Callback when path changes ---@return userdata - UI component function M.create_settings_section(install_path, on_change) - return editor.ui.vertical({ - spacing = editor.ui.SPACING.SMALL, - children = { - editor.ui.label({ - text = "Installation Folder:", - color = editor.ui.COLOR.TEXT - }), - editor.ui.label({ - text = install_path, - color = editor.ui.COLOR.TEXT, - grow = true - }) - } - }) + return editor.ui.vertical({ + spacing = editor.ui.SPACING.SMALL, + children = { + editor.ui.label({ + text = "Installation Folder:", + color = editor.ui.COLOR.TEXT + }), + editor.ui.label({ + text = install_path, + color = editor.ui.COLOR.TEXT, + grow = true + }) + } + }) end @@ -30,18 +30,18 @@ end ---@param items table - List of widget items ---@return table - Sorted list of unique authors local function extract_authors(items) - local authors = {} - local author_set = {} + local authors = {} + local author_set = {} - for _, item in ipairs(items) do - if item.author and not author_set[item.author] then - author_set[item.author] = true - table.insert(authors, item.author) - end - end + for _, item in ipairs(items) do + if item.author and not author_set[item.author] then + author_set[item.author] = true + table.insert(authors, item.author) + end + end - table.sort(authors) - return authors + table.sort(authors) + return authors end @@ -49,22 +49,22 @@ end ---@param items table - List of widget items ---@return table - Sorted list of unique tags local function extract_tags(items) - local tags = {} - local tag_set = {} + local tags = {} + local tag_set = {} - for _, item in ipairs(items) do - if item.tags then - for _, tag in ipairs(item.tags) do - if not tag_set[tag] then - tag_set[tag] = true - table.insert(tags, tag) - end - end - end - end + for _, item in ipairs(items) do + if item.tags then + for _, tag in ipairs(item.tags) do + if not tag_set[tag] then + tag_set[tag] = true + table.insert(tags, tag) + end + end + end + end - table.sort(tags) - return tags + table.sort(tags) + return tags end @@ -76,52 +76,52 @@ end ---@param on_tag_change function - Callback for tag filter change ---@return userdata - UI component function M.create_filter_section(items, author_filter, tag_filter, on_author_change, on_tag_change) - local authors = extract_authors(items) - local tags = extract_tags(items) + local authors = extract_authors(items) + local tags = extract_tags(items) - -- Build author options - local author_options = {"All Authors"} - for _, author in ipairs(authors) do - table.insert(author_options, author) - end + -- Build author options + local author_options = {"All Authors"} + for _, author in ipairs(authors) do + table.insert(author_options, author) + end - -- Build tag options - local tag_options = {"All Categories"} - for _, tag in ipairs(tags) do - table.insert(tag_options, tag) - end + -- Build tag options + local tag_options = {"All Categories"} + for _, tag in ipairs(tags) do + table.insert(tag_options, tag) + end - return editor.ui.horizontal({ - spacing = editor.ui.SPACING.MEDIUM, - children = { - editor.ui.vertical({ - spacing = editor.ui.SPACING.SMALL, - children = { - editor.ui.label({ - text = "Author:", - color = editor.ui.COLOR.TEXT - }), - editor.ui.label({ - text = author_filter, - color = editor.ui.COLOR.TEXT - }) - } - }), - editor.ui.vertical({ - spacing = editor.ui.SPACING.SMALL, - children = { - editor.ui.label({ - text = "Category:", - color = editor.ui.COLOR.TEXT - }), - editor.ui.label({ - text = tag_filter, - color = editor.ui.COLOR.TEXT - }) - } - }) - } - }) + return editor.ui.horizontal({ + spacing = editor.ui.SPACING.MEDIUM, + children = { + editor.ui.vertical({ + spacing = editor.ui.SPACING.SMALL, + children = { + editor.ui.label({ + text = "Author:", + color = editor.ui.COLOR.TEXT + }), + editor.ui.label({ + text = author_filter, + color = editor.ui.COLOR.TEXT + }) + } + }), + editor.ui.vertical({ + spacing = editor.ui.SPACING.SMALL, + children = { + editor.ui.label({ + text = "Category:", + color = editor.ui.COLOR.TEXT + }), + editor.ui.label({ + text = tag_filter, + color = editor.ui.COLOR.TEXT + }) + } + }) + } + }) end @@ -129,13 +129,13 @@ end ---@param size_bytes number - Size in bytes ---@return string - Formatted size string local function format_size(size_bytes) - if size_bytes < 1024 then - return size_bytes .. " B" - elseif size_bytes < 1024 * 1024 then - return math.floor(size_bytes / 1024) .. " KB" - else - return math.floor(size_bytes / (1024 * 1024)) .. " MB" - end + if size_bytes < 1024 then + return size_bytes .. " B" + elseif size_bytes < 1024 * 1024 then + return math.floor(size_bytes / 1024) .. " KB" + else + return math.floor(size_bytes / (1024 * 1024)) .. " MB" + end end @@ -146,101 +146,99 @@ end ---@param on_open_api function - Callback for API docs button ---@return userdata - UI component function M.create_widget_item(item, is_installed, on_install, on_open_api) - local size_text = item.size and format_size(item.size) or "Unknown size" - local version_text = item.version and "v" .. item.version or "Unknown version" + local size_text = item.size and format_size(item.size) or "Unknown size" + local version_text = item.version and "v" .. item.version or "Unknown version" - -- Create tags display - local tags_text = "" - if item.tags and #item.tags > 0 then - tags_text = "Tags: " .. table.concat(item.tags, ", ") - end + -- Create tags display + local tags_text = "" + if item.tags and #item.tags > 0 then + tags_text = "Tags: " .. table.concat(item.tags, ", ") + end - -- Create dependencies display - local deps_text = "" - if item.depends and #item.depends > 0 then - deps_text = "Depends on: " .. table.concat(item.depends, ", ") - end + -- Create dependencies display + local deps_text = "" + if item.depends and #item.depends > 0 then + deps_text = "Depends on: " .. table.concat(item.depends, ", ") + end - return editor.ui.horizontal({ - spacing = editor.ui.SPACING.MEDIUM, - padding = editor.ui.PADDING.MEDIUM, - children = { - -- Widget icon placeholder - editor.ui.label({ - text = "📦", - color = editor.ui.COLOR.HINT - }), + return editor.ui.horizontal({ + spacing = editor.ui.SPACING.MEDIUM, + padding = editor.ui.PADDING.MEDIUM, + children = { + -- Widget icon placeholder + editor.ui.label({ + text = "📦", + color = editor.ui.COLOR.HINT + }), - -- Widget details - editor.ui.vertical({ - spacing = editor.ui.SPACING.SMALL, - grow = true, - children = { - -- Title and author - editor.ui.horizontal({ - spacing = editor.ui.SPACING.SMALL, - children = { - editor.ui.label({ - text = item.title or item.id, - color = editor.ui.COLOR.TEXT - }), - editor.ui.label({ - text = "by " .. (item.author or "Unknown"), - color = editor.ui.COLOR.HINT - }) - } - }), + -- Widget details + editor.ui.vertical({ + spacing = editor.ui.SPACING.SMALL, + grow = true, + children = { + -- Title and author + editor.ui.horizontal({ + spacing = editor.ui.SPACING.SMALL, + children = { + editor.ui.label({ + text = item.title or item.id, + color = editor.ui.COLOR.TEXT + }), + editor.ui.label({ + text = "by " .. (item.author or "Unknown"), + color = editor.ui.COLOR.HINT + }), + editor.ui.label({ + text = version_text .. " • " .. size_text, + color = editor.ui.COLOR.HINT + }), + } + }), - -- Version and size - editor.ui.label({ - text = version_text .. " • " .. size_text, - color = editor.ui.COLOR.HINT - }), + -- Description + editor.ui.label({ + text = item.description or "No description available", + color = editor.ui.COLOR.TEXT + }), - -- Description - editor.ui.label({ - text = item.description or "No description available", - color = editor.ui.COLOR.TEXT - }), + -- Tags + tags_text ~= "" and editor.ui.label({ + text = tags_text, + color = editor.ui.COLOR.HINT + }) or nil, - -- Tags - tags_text ~= "" and editor.ui.label({ - text = tags_text, - color = editor.ui.COLOR.HINT - }) or nil, + -- Dependencies + deps_text ~= "" and editor.ui.label({ + text = deps_text, + color = editor.ui.COLOR.WARNING + }) or nil, - -- Dependencies - deps_text ~= "" and editor.ui.label({ - text = deps_text, - color = editor.ui.COLOR.WARNING - }) or nil, + -- Installation status + is_installed and editor.ui.label({ + text = "✓ Already installed", + color = editor.ui.COLOR.HINT + }) or nil + } + }), - -- Installation status - is_installed and editor.ui.label({ - text = "✓ Already installed", - color = editor.ui.COLOR.HINT - }) or nil - } - }), - - -- Action buttons - editor.ui.vertical({ - spacing = editor.ui.SPACING.SMALL, - children = { - editor.ui.button({ - text = is_installed and "Reinstall" or "Install", - on_pressed = on_install, - enabled = true - }), - editor.ui.button({ - text = "API Docs", - on_pressed = on_open_api, - enabled = item.api ~= nil - }) - } - }) - } - }) + -- Action buttons + editor.ui.vertical({ + spacing = editor.ui.SPACING.SMALL, + children = { + editor.ui.button({ + text = is_installed and "Reinstall" or "Install", + on_pressed = on_install, + enabled = true + }), + editor.ui.button({ + text = "API", + on_pressed = on_open_api, + enabled = item.api ~= nil + }) + } + }) + } + }) end @@ -251,29 +249,23 @@ end ---@param on_open_api function - Callback for API docs button ---@return userdata - UI component function M.create_widget_list(items, is_installed_func, on_install, on_open_api) - local widget_items = {} + local widget_items = {} - for _, item in ipairs(items) do - local is_installed = is_installed_func and is_installed_func(item) or false + for index = 1, 9 do + for _, item in ipairs(items) do + local is_installed = is_installed_func and is_installed_func(item) or false - table.insert(widget_items, M.create_widget_item(item, is_installed, - function() on_install(item) end, - function() on_open_api(item) end - )) + table.insert(widget_items, M.create_widget_item(item, is_installed, + function() on_install(item) end, + function() on_open_api(item) end + )) + end + end - -- Add separator between items (except for the last one) - if _ < #items then - table.insert(widget_items, editor.ui.label({ - text = "---", - color = editor.ui.COLOR.HINT - })) - end - end - - return editor.ui.vertical({ - spacing = editor.ui.SPACING.SMALL, - children = widget_items - }) + return editor.ui.vertical({ + spacing = editor.ui.SPACING.SMALL, + children = widget_items + }) end @@ -281,17 +273,17 @@ end ---@param message string - Loading message ---@return userdata - UI component function M.create_loading_indicator(message) - return editor.ui.vertical({ - spacing = editor.ui.SPACING.MEDIUM, - alignment = editor.ui.ALIGNMENT.CENTER, - children = { - editor.ui.label({ - text = message or "Loading...", - color = editor.ui.COLOR.TEXT, - alignment = editor.ui.ALIGNMENT.CENTER - }) - } - }) + return editor.ui.vertical({ + spacing = editor.ui.SPACING.MEDIUM, + alignment = editor.ui.ALIGNMENT.CENTER, + children = { + editor.ui.label({ + text = message or "Loading...", + color = editor.ui.COLOR.TEXT, + alignment = editor.ui.ALIGNMENT.CENTER + }) + } + }) end @@ -299,17 +291,17 @@ end ---@param message string - Error message ---@return userdata - UI component function M.create_error_message(message) - return editor.ui.vertical({ - spacing = editor.ui.SPACING.MEDIUM, - alignment = editor.ui.ALIGNMENT.CENTER, - children = { - editor.ui.label({ - text = "Error: " .. message, - color = editor.ui.COLOR.ERROR, - alignment = editor.ui.ALIGNMENT.CENTER - }) - } - }) + return editor.ui.vertical({ + spacing = editor.ui.SPACING.MEDIUM, + alignment = editor.ui.ALIGNMENT.CENTER, + children = { + editor.ui.label({ + text = "Error: " .. message, + color = editor.ui.COLOR.ERROR, + alignment = editor.ui.ALIGNMENT.CENTER + }) + } + }) end