mirror of
https://github.com/Insality/druid.git
synced 2025-11-26 10:50:52 +01:00
Update
This commit is contained in:
@@ -134,6 +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")
|
||||||
-- 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)
|
||||||
|
|||||||
35
druid/editor_scripts/core/base64.lua
Normal file
35
druid/editor_scripts/core/base64.lua
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
-- base64 encode/decode (http://lua-users.org/wiki/BaseSixtyFour)
|
||||||
|
|
||||||
|
local M = {}
|
||||||
|
|
||||||
|
local b='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||||
|
|
||||||
|
function M.encode(data)
|
||||||
|
return ((data:gsub('.', function(x)
|
||||||
|
local r,b='',x:byte()
|
||||||
|
for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
|
||||||
|
return r;
|
||||||
|
end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
|
||||||
|
if (#x < 6) then return '' end
|
||||||
|
local c=0
|
||||||
|
for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
|
||||||
|
return b:sub(c+1,c+1)
|
||||||
|
end)..({ '', '==', '=' })[#data%3+1])
|
||||||
|
end
|
||||||
|
|
||||||
|
function M.decode(data)
|
||||||
|
data = string.gsub(data, '[^'..b..'=]', '')
|
||||||
|
return (data:gsub('.', function(x)
|
||||||
|
if (x == '=') then return '' end
|
||||||
|
local r,f='',(b:find(x)-1)
|
||||||
|
for i=6,1,-1 do r=r..(f%2^i-f%2^(i-1)>0 and '1' or '0') end
|
||||||
|
return r;
|
||||||
|
end):gsub('%d%d%d?%d?%d?%d?%d?%d?', function(x)
|
||||||
|
if (#x ~= 8) then return '' end
|
||||||
|
local c=0
|
||||||
|
for i=1,8 do c=c+(x:sub(i,i)=='1' and 2^(8-i) or 0) end
|
||||||
|
return string.char(c)
|
||||||
|
end))
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
@@ -1,92 +1,83 @@
|
|||||||
|
local base64 = require("druid.editor_scripts.core.base64")
|
||||||
--- 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
|
||||||
|
---@field id string
|
||||||
|
---@field version string
|
||||||
|
---@field title string
|
||||||
|
---@field author string
|
||||||
|
---@field description string
|
||||||
|
---@field api string
|
||||||
|
---@field author_url string
|
||||||
|
---@field image string
|
||||||
|
---@field manifest_url string
|
||||||
|
---@field zip_url string
|
||||||
|
---@field json_zip_url string
|
||||||
|
---@field sha256 string
|
||||||
|
---@field size number
|
||||||
|
---@field depends string[]
|
||||||
|
---@field tags string[]
|
||||||
|
|
||||||
|
|
||||||
---Download a file from URL
|
---Download a file from URL
|
||||||
---@param url string - The URL to download from
|
---@param url string - The URL to download from
|
||||||
---@return string|nil, string|nil - Downloaded content or nil, error message or nil
|
---@return string|nil, string|nil - Downloaded content or nil, filename or nil
|
||||||
local function download_file(url)
|
local function download_file_zip_json(url)
|
||||||
print("Downloading from:", url)
|
local response = http.request(url, { as = "json" })
|
||||||
|
|
||||||
-- Try different approaches for downloading binary data
|
|
||||||
local success, response = pcall(function()
|
|
||||||
-- First try without specifying 'as' parameter
|
|
||||||
return http.request(url)
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- If that fails, try with 'as = "string"'
|
|
||||||
if not success or not response or not response.body then
|
|
||||||
print("First attempt failed, trying with as='string'")
|
|
||||||
success, response = pcall(function()
|
|
||||||
return http.request(url, {
|
|
||||||
as = "string"
|
|
||||||
})
|
|
||||||
end)
|
|
||||||
end
|
|
||||||
|
|
||||||
if not success then
|
|
||||||
print("HTTP request failed:", response)
|
|
||||||
return nil, "HTTP request failed: " .. tostring(response)
|
|
||||||
end
|
|
||||||
|
|
||||||
if not response then
|
|
||||||
print("No response received")
|
|
||||||
return nil, "No response received from server"
|
|
||||||
end
|
|
||||||
|
|
||||||
print("Response status:", response.status)
|
|
||||||
print("Response body type:", type(response.body))
|
|
||||||
print("Response body length:", response.body and #response.body or "nil")
|
|
||||||
if response.headers then
|
|
||||||
print("Response headers:", response.headers["content-type"] or "unknown")
|
|
||||||
print("Content length header:", response.headers["content-length"] or "unknown")
|
|
||||||
end
|
|
||||||
|
|
||||||
if response.status ~= 200 then
|
if response.status ~= 200 then
|
||||||
return nil, "Failed to download file. HTTP status: " .. tostring(response.status)
|
print("Failed to download file. HTTP status: " .. response.status)
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if not response.body then
|
local data = response.body
|
||||||
return nil, "No content received from server"
|
|
||||||
end
|
|
||||||
|
|
||||||
print("Downloaded", #response.body, "bytes")
|
return base64.decode(data.data), data.filename
|
||||||
return response.body, nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
---Install a widget from a zip URL
|
---Install a widget from a zip URL
|
||||||
---@param item table - Widget item data containing zip_url and id
|
---@param item druid.core.item_info - Widget item data containing zip_url and id
|
||||||
---@param install_folder string - Target folder to install to
|
---@param install_folder string - Target folder to install to
|
||||||
---@return boolean, string - Success status and message
|
---@return boolean, string - Success status and message
|
||||||
function M.install_widget(item, install_folder)
|
function M.install_widget(item, install_folder)
|
||||||
if not item.zip_url or not item.id then
|
if not item.json_zip_url or not item.id then
|
||||||
return false, "Invalid widget data: missing zip_url or id"
|
return false, "Invalid widget data: missing zip_url or id"
|
||||||
end
|
end
|
||||||
|
|
||||||
print("Installing widget:", item.id)
|
|
||||||
print("Download URL:", item.zip_url)
|
|
||||||
print("Target folder:", install_folder)
|
|
||||||
|
|
||||||
-- Download the zip file
|
-- Download the zip file
|
||||||
local zip_data, download_error = download_file(item.zip_url)
|
local zip_data, filename = download_file_zip_json(item.json_zip_url)
|
||||||
if not zip_data then
|
if not zip_data or not filename then
|
||||||
return false, "Failed to download widget: " .. download_error
|
return false, "Failed to download widget: " .. filename
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create a simple success message for now
|
|
||||||
local success = true
|
|
||||||
local message = "Widget '" .. item.id .. "' downloaded successfully!"
|
|
||||||
message = message .. "\nDownload URL: " .. item.zip_url
|
|
||||||
message = message .. "\nSize: " .. tostring(#zip_data) .. " bytes"
|
|
||||||
message = message .. "\nTarget folder: " .. install_folder
|
|
||||||
|
|
||||||
print("Successfully downloaded widget:", item.id)
|
local zip_file_path = install_folder .. "/" .. filename
|
||||||
return success, message
|
local zip_file = io.open(zip_file_path, "wb")
|
||||||
|
if not zip_file then
|
||||||
|
return false, "Failed to open zip file: " .. zip_file_path
|
||||||
|
end
|
||||||
|
|
||||||
|
zip_file:write(zip_data)
|
||||||
|
zip_file:close()
|
||||||
|
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)
|
||||||
|
print("Widget unpacked successfully")
|
||||||
|
|
||||||
|
-- Remove the zip file
|
||||||
|
os.remove(zip_file_path)
|
||||||
|
print("Zip file removed successfully")
|
||||||
|
|
||||||
|
|
||||||
|
return true, "Widget installed successfully"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user