mirror of
https://github.com/Insality/druid.git
synced 2025-11-26 10:50:52 +01:00
Update
This commit is contained in:
@@ -134,7 +134,7 @@ function M.open_asset_store()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local dialog_component = editor.ui.component(function(props)
|
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
|
-- State management
|
||||||
local items, set_items = editor.ui.use_state(initial_items)
|
local items, set_items = editor.ui.use_state(initial_items)
|
||||||
local loading, set_loading = editor.ui.use_state(initial_loading)
|
local loading, set_loading = editor.ui.use_state(initial_loading)
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
local base64 = require("druid.editor_scripts.core.base64")
|
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
|
--- Module for handling widget installation from zip files
|
||||||
--- Downloads zip files and extracts them to the specified folder
|
--- Downloads zip files and extracts them to the specified folder
|
||||||
|
|
||||||
local M = {}
|
local M = {}
|
||||||
|
|
||||||
local DEFAULT_INSTALL_FOLDER = "./widget"
|
local DEFAULT_INSTALL_FOLDER = "/widget"
|
||||||
|
|
||||||
---@class druid.core.item_info
|
---@class druid.core.item_info
|
||||||
---@field id string
|
---@field id string
|
||||||
@@ -57,7 +58,7 @@ function M.install_widget(item, install_folder)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local zip_file_path = install_folder .. "/" .. filename
|
local zip_file_path = "." .. install_folder .. "/" .. filename
|
||||||
local zip_file = io.open(zip_file_path, "wb")
|
local zip_file = io.open(zip_file_path, "wb")
|
||||||
if not zip_file then
|
if not zip_file then
|
||||||
return false, "Failed to open zip file: " .. zip_file_path
|
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)
|
print("Zip written to file: " .. zip_file_path)
|
||||||
|
|
||||||
-- Unzip the zip file
|
-- Unzip the zip file
|
||||||
local folder_name = item.id .. "-" .. item.version
|
local folder_path = "." .. install_folder .. "/" .. item.id
|
||||||
zip.unpack(zip_file_path, install_folder .. "/" .. folder_name)
|
|
||||||
|
zip.unpack(zip_file_path, folder_path)
|
||||||
print("Widget unpacked successfully")
|
print("Widget unpacked successfully")
|
||||||
|
|
||||||
-- Remove the zip file
|
-- Remove the zip file
|
||||||
os.remove(zip_file_path)
|
os.remove(zip_file_path)
|
||||||
print("Zip file removed successfully")
|
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"
|
return true, "Widget installed successfully"
|
||||||
end
|
end
|
||||||
|
|||||||
22
druid/editor_scripts/core/path_replacer.lua
Normal file
22
druid/editor_scripts/core/path_replacer.lua
Normal file
@@ -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
|
||||||
@@ -9,20 +9,20 @@ local M = {}
|
|||||||
---@param on_change function - Callback when path changes
|
---@param on_change function - Callback when path changes
|
||||||
---@return userdata - UI component
|
---@return userdata - UI component
|
||||||
function M.create_settings_section(install_path, on_change)
|
function M.create_settings_section(install_path, on_change)
|
||||||
return editor.ui.vertical({
|
return editor.ui.vertical({
|
||||||
spacing = editor.ui.SPACING.SMALL,
|
spacing = editor.ui.SPACING.SMALL,
|
||||||
children = {
|
children = {
|
||||||
editor.ui.label({
|
editor.ui.label({
|
||||||
text = "Installation Folder:",
|
text = "Installation Folder:",
|
||||||
color = editor.ui.COLOR.TEXT
|
color = editor.ui.COLOR.TEXT
|
||||||
}),
|
}),
|
||||||
editor.ui.label({
|
editor.ui.label({
|
||||||
text = install_path,
|
text = install_path,
|
||||||
color = editor.ui.COLOR.TEXT,
|
color = editor.ui.COLOR.TEXT,
|
||||||
grow = true
|
grow = true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -30,18 +30,18 @@ end
|
|||||||
---@param items table - List of widget items
|
---@param items table - List of widget items
|
||||||
---@return table - Sorted list of unique authors
|
---@return table - Sorted list of unique authors
|
||||||
local function extract_authors(items)
|
local function extract_authors(items)
|
||||||
local authors = {}
|
local authors = {}
|
||||||
local author_set = {}
|
local author_set = {}
|
||||||
|
|
||||||
for _, item in ipairs(items) do
|
for _, item in ipairs(items) do
|
||||||
if item.author and not author_set[item.author] then
|
if item.author and not author_set[item.author] then
|
||||||
author_set[item.author] = true
|
author_set[item.author] = true
|
||||||
table.insert(authors, item.author)
|
table.insert(authors, item.author)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
table.sort(authors)
|
table.sort(authors)
|
||||||
return authors
|
return authors
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -49,22 +49,22 @@ end
|
|||||||
---@param items table - List of widget items
|
---@param items table - List of widget items
|
||||||
---@return table - Sorted list of unique tags
|
---@return table - Sorted list of unique tags
|
||||||
local function extract_tags(items)
|
local function extract_tags(items)
|
||||||
local tags = {}
|
local tags = {}
|
||||||
local tag_set = {}
|
local tag_set = {}
|
||||||
|
|
||||||
for _, item in ipairs(items) do
|
for _, item in ipairs(items) do
|
||||||
if item.tags then
|
if item.tags then
|
||||||
for _, tag in ipairs(item.tags) do
|
for _, tag in ipairs(item.tags) do
|
||||||
if not tag_set[tag] then
|
if not tag_set[tag] then
|
||||||
tag_set[tag] = true
|
tag_set[tag] = true
|
||||||
table.insert(tags, tag)
|
table.insert(tags, tag)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
table.sort(tags)
|
table.sort(tags)
|
||||||
return tags
|
return tags
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -76,52 +76,52 @@ end
|
|||||||
---@param on_tag_change function - Callback for tag filter change
|
---@param on_tag_change function - Callback for tag filter change
|
||||||
---@return userdata - UI component
|
---@return userdata - UI component
|
||||||
function M.create_filter_section(items, author_filter, tag_filter, on_author_change, on_tag_change)
|
function M.create_filter_section(items, author_filter, tag_filter, on_author_change, on_tag_change)
|
||||||
local authors = extract_authors(items)
|
local authors = extract_authors(items)
|
||||||
local tags = extract_tags(items)
|
local tags = extract_tags(items)
|
||||||
|
|
||||||
-- Build author options
|
-- Build author options
|
||||||
local author_options = {"All Authors"}
|
local author_options = {"All Authors"}
|
||||||
for _, author in ipairs(authors) do
|
for _, author in ipairs(authors) do
|
||||||
table.insert(author_options, author)
|
table.insert(author_options, author)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Build tag options
|
-- Build tag options
|
||||||
local tag_options = {"All Categories"}
|
local tag_options = {"All Categories"}
|
||||||
for _, tag in ipairs(tags) do
|
for _, tag in ipairs(tags) do
|
||||||
table.insert(tag_options, tag)
|
table.insert(tag_options, tag)
|
||||||
end
|
end
|
||||||
|
|
||||||
return editor.ui.horizontal({
|
return editor.ui.horizontal({
|
||||||
spacing = editor.ui.SPACING.MEDIUM,
|
spacing = editor.ui.SPACING.MEDIUM,
|
||||||
children = {
|
children = {
|
||||||
editor.ui.vertical({
|
editor.ui.vertical({
|
||||||
spacing = editor.ui.SPACING.SMALL,
|
spacing = editor.ui.SPACING.SMALL,
|
||||||
children = {
|
children = {
|
||||||
editor.ui.label({
|
editor.ui.label({
|
||||||
text = "Author:",
|
text = "Author:",
|
||||||
color = editor.ui.COLOR.TEXT
|
color = editor.ui.COLOR.TEXT
|
||||||
}),
|
}),
|
||||||
editor.ui.label({
|
editor.ui.label({
|
||||||
text = author_filter,
|
text = author_filter,
|
||||||
color = editor.ui.COLOR.TEXT
|
color = editor.ui.COLOR.TEXT
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
editor.ui.vertical({
|
editor.ui.vertical({
|
||||||
spacing = editor.ui.SPACING.SMALL,
|
spacing = editor.ui.SPACING.SMALL,
|
||||||
children = {
|
children = {
|
||||||
editor.ui.label({
|
editor.ui.label({
|
||||||
text = "Category:",
|
text = "Category:",
|
||||||
color = editor.ui.COLOR.TEXT
|
color = editor.ui.COLOR.TEXT
|
||||||
}),
|
}),
|
||||||
editor.ui.label({
|
editor.ui.label({
|
||||||
text = tag_filter,
|
text = tag_filter,
|
||||||
color = editor.ui.COLOR.TEXT
|
color = editor.ui.COLOR.TEXT
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -129,13 +129,13 @@ end
|
|||||||
---@param size_bytes number - Size in bytes
|
---@param size_bytes number - Size in bytes
|
||||||
---@return string - Formatted size string
|
---@return string - Formatted size string
|
||||||
local function format_size(size_bytes)
|
local function format_size(size_bytes)
|
||||||
if size_bytes < 1024 then
|
if size_bytes < 1024 then
|
||||||
return size_bytes .. " B"
|
return size_bytes .. " B"
|
||||||
elseif size_bytes < 1024 * 1024 then
|
elseif size_bytes < 1024 * 1024 then
|
||||||
return math.floor(size_bytes / 1024) .. " KB"
|
return math.floor(size_bytes / 1024) .. " KB"
|
||||||
else
|
else
|
||||||
return math.floor(size_bytes / (1024 * 1024)) .. " MB"
|
return math.floor(size_bytes / (1024 * 1024)) .. " MB"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -146,101 +146,99 @@ end
|
|||||||
---@param on_open_api function - Callback for API docs button
|
---@param on_open_api function - Callback for API docs button
|
||||||
---@return userdata - UI component
|
---@return userdata - UI component
|
||||||
function M.create_widget_item(item, is_installed, on_install, on_open_api)
|
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 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 version_text = item.version and "v" .. item.version or "Unknown version"
|
||||||
|
|
||||||
-- Create tags display
|
-- Create tags display
|
||||||
local tags_text = ""
|
local tags_text = ""
|
||||||
if item.tags and #item.tags > 0 then
|
if item.tags and #item.tags > 0 then
|
||||||
tags_text = "Tags: " .. table.concat(item.tags, ", ")
|
tags_text = "Tags: " .. table.concat(item.tags, ", ")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create dependencies display
|
-- Create dependencies display
|
||||||
local deps_text = ""
|
local deps_text = ""
|
||||||
if item.depends and #item.depends > 0 then
|
if item.depends and #item.depends > 0 then
|
||||||
deps_text = "Depends on: " .. table.concat(item.depends, ", ")
|
deps_text = "Depends on: " .. table.concat(item.depends, ", ")
|
||||||
end
|
end
|
||||||
|
|
||||||
return editor.ui.horizontal({
|
return editor.ui.horizontal({
|
||||||
spacing = editor.ui.SPACING.MEDIUM,
|
spacing = editor.ui.SPACING.MEDIUM,
|
||||||
padding = editor.ui.PADDING.MEDIUM,
|
padding = editor.ui.PADDING.MEDIUM,
|
||||||
children = {
|
children = {
|
||||||
-- Widget icon placeholder
|
-- Widget icon placeholder
|
||||||
editor.ui.label({
|
editor.ui.label({
|
||||||
text = "📦",
|
text = "📦",
|
||||||
color = editor.ui.COLOR.HINT
|
color = editor.ui.COLOR.HINT
|
||||||
}),
|
}),
|
||||||
|
|
||||||
-- Widget details
|
-- Widget details
|
||||||
editor.ui.vertical({
|
editor.ui.vertical({
|
||||||
spacing = editor.ui.SPACING.SMALL,
|
spacing = editor.ui.SPACING.SMALL,
|
||||||
grow = true,
|
grow = true,
|
||||||
children = {
|
children = {
|
||||||
-- Title and author
|
-- Title and author
|
||||||
editor.ui.horizontal({
|
editor.ui.horizontal({
|
||||||
spacing = editor.ui.SPACING.SMALL,
|
spacing = editor.ui.SPACING.SMALL,
|
||||||
children = {
|
children = {
|
||||||
editor.ui.label({
|
editor.ui.label({
|
||||||
text = item.title or item.id,
|
text = item.title or item.id,
|
||||||
color = editor.ui.COLOR.TEXT
|
color = editor.ui.COLOR.TEXT
|
||||||
}),
|
}),
|
||||||
editor.ui.label({
|
editor.ui.label({
|
||||||
text = "by " .. (item.author or "Unknown"),
|
text = "by " .. (item.author or "Unknown"),
|
||||||
color = editor.ui.COLOR.HINT
|
color = editor.ui.COLOR.HINT
|
||||||
})
|
}),
|
||||||
}
|
editor.ui.label({
|
||||||
}),
|
text = version_text .. " • " .. size_text,
|
||||||
|
color = editor.ui.COLOR.HINT
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
-- Version and size
|
-- Description
|
||||||
editor.ui.label({
|
editor.ui.label({
|
||||||
text = version_text .. " • " .. size_text,
|
text = item.description or "No description available",
|
||||||
color = editor.ui.COLOR.HINT
|
color = editor.ui.COLOR.TEXT
|
||||||
}),
|
}),
|
||||||
|
|
||||||
-- Description
|
-- Tags
|
||||||
editor.ui.label({
|
tags_text ~= "" and editor.ui.label({
|
||||||
text = item.description or "No description available",
|
text = tags_text,
|
||||||
color = editor.ui.COLOR.TEXT
|
color = editor.ui.COLOR.HINT
|
||||||
}),
|
}) or nil,
|
||||||
|
|
||||||
-- Tags
|
-- Dependencies
|
||||||
tags_text ~= "" and editor.ui.label({
|
deps_text ~= "" and editor.ui.label({
|
||||||
text = tags_text,
|
text = deps_text,
|
||||||
color = editor.ui.COLOR.HINT
|
color = editor.ui.COLOR.WARNING
|
||||||
}) or nil,
|
}) or nil,
|
||||||
|
|
||||||
-- Dependencies
|
-- Installation status
|
||||||
deps_text ~= "" and editor.ui.label({
|
is_installed and editor.ui.label({
|
||||||
text = deps_text,
|
text = "✓ Already installed",
|
||||||
color = editor.ui.COLOR.WARNING
|
color = editor.ui.COLOR.HINT
|
||||||
}) or nil,
|
}) or nil
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
|
||||||
-- Installation status
|
-- Action buttons
|
||||||
is_installed and editor.ui.label({
|
editor.ui.vertical({
|
||||||
text = "✓ Already installed",
|
spacing = editor.ui.SPACING.SMALL,
|
||||||
color = editor.ui.COLOR.HINT
|
children = {
|
||||||
}) or nil
|
editor.ui.button({
|
||||||
}
|
text = is_installed and "Reinstall" or "Install",
|
||||||
}),
|
on_pressed = on_install,
|
||||||
|
enabled = true
|
||||||
-- Action buttons
|
}),
|
||||||
editor.ui.vertical({
|
editor.ui.button({
|
||||||
spacing = editor.ui.SPACING.SMALL,
|
text = "API",
|
||||||
children = {
|
on_pressed = on_open_api,
|
||||||
editor.ui.button({
|
enabled = item.api ~= nil
|
||||||
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
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -251,29 +249,23 @@ end
|
|||||||
---@param on_open_api function - Callback for API docs button
|
---@param on_open_api function - Callback for API docs button
|
||||||
---@return userdata - UI component
|
---@return userdata - UI component
|
||||||
function M.create_widget_list(items, is_installed_func, on_install, on_open_api)
|
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
|
for index = 1, 9 do
|
||||||
local is_installed = is_installed_func and is_installed_func(item) or false
|
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,
|
table.insert(widget_items, M.create_widget_item(item, is_installed,
|
||||||
function() on_install(item) end,
|
function() on_install(item) end,
|
||||||
function() on_open_api(item) end
|
function() on_open_api(item) end
|
||||||
))
|
))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Add separator between items (except for the last one)
|
return editor.ui.vertical({
|
||||||
if _ < #items then
|
spacing = editor.ui.SPACING.SMALL,
|
||||||
table.insert(widget_items, editor.ui.label({
|
children = widget_items
|
||||||
text = "---",
|
})
|
||||||
color = editor.ui.COLOR.HINT
|
|
||||||
}))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return editor.ui.vertical({
|
|
||||||
spacing = editor.ui.SPACING.SMALL,
|
|
||||||
children = widget_items
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -281,17 +273,17 @@ end
|
|||||||
---@param message string - Loading message
|
---@param message string - Loading message
|
||||||
---@return userdata - UI component
|
---@return userdata - UI component
|
||||||
function M.create_loading_indicator(message)
|
function M.create_loading_indicator(message)
|
||||||
return editor.ui.vertical({
|
return editor.ui.vertical({
|
||||||
spacing = editor.ui.SPACING.MEDIUM,
|
spacing = editor.ui.SPACING.MEDIUM,
|
||||||
alignment = editor.ui.ALIGNMENT.CENTER,
|
alignment = editor.ui.ALIGNMENT.CENTER,
|
||||||
children = {
|
children = {
|
||||||
editor.ui.label({
|
editor.ui.label({
|
||||||
text = message or "Loading...",
|
text = message or "Loading...",
|
||||||
color = editor.ui.COLOR.TEXT,
|
color = editor.ui.COLOR.TEXT,
|
||||||
alignment = editor.ui.ALIGNMENT.CENTER
|
alignment = editor.ui.ALIGNMENT.CENTER
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -299,17 +291,17 @@ end
|
|||||||
---@param message string - Error message
|
---@param message string - Error message
|
||||||
---@return userdata - UI component
|
---@return userdata - UI component
|
||||||
function M.create_error_message(message)
|
function M.create_error_message(message)
|
||||||
return editor.ui.vertical({
|
return editor.ui.vertical({
|
||||||
spacing = editor.ui.SPACING.MEDIUM,
|
spacing = editor.ui.SPACING.MEDIUM,
|
||||||
alignment = editor.ui.ALIGNMENT.CENTER,
|
alignment = editor.ui.ALIGNMENT.CENTER,
|
||||||
children = {
|
children = {
|
||||||
editor.ui.label({
|
editor.ui.label({
|
||||||
text = "Error: " .. message,
|
text = "Error: " .. message,
|
||||||
color = editor.ui.COLOR.ERROR,
|
color = editor.ui.COLOR.ERROR,
|
||||||
alignment = editor.ui.ALIGNMENT.CENTER
|
alignment = editor.ui.ALIGNMENT.CENTER
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user