Skip to content

Commit

Permalink
test partial pack loading
Browse files Browse the repository at this point in the history
  • Loading branch information
Bauumm committed Feb 5, 2024
1 parent 6662313 commit c2e2e01
Show file tree
Hide file tree
Showing 2 changed files with 111 additions and 117 deletions.
8 changes: 5 additions & 3 deletions ui/overlay/packs/download_thread.lua
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,13 @@ function download.set_server(serv_url, http_port, https_port)
server_https_url = "https://" .. serv_url .. ":" .. https_port .. "/"
end

---gets a list of pack names for the specified game version
---gets a list of packs
---@param start number
---@param stop number
---@return table
function download.get_pack_list()
function download.get_pack_list(start, stop)
if not pack_data_list then
pack_data_list = api("get_packs")
pack_data_list = api(("get_packs/%d/%d"):format(start, stop))
if not pack_data_list then
return {}
end
Expand Down
220 changes: 106 additions & 114 deletions ui/overlay/packs/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -20,132 +20,120 @@ local log = require("log")(...)
download.set_server(config.get("server_url"), config.get("server_http_api_port"), config.get("server_https_api_port"))

local pack_overlay = overlay:new()
local loading = label:new("Loading...")

local pack_list = flex:new({
loading,
}, { direction = "column", align_items = "stretch" })

local pack_list = flex:new({}, { direction = "column", align_items = "stretch" })
local selected_version = 21
local version_buttons
local ongoing_downloads = {}
local pack_id_elem_map = {}

local create_pack_list = async(function()
pack_list.elements = { label:new("Loading...") }
pack_list:mutated(false)
pack_list.elements[1]:update_size()
local old_version = selected_version
local packs = async.await(download.get_pack_list())
if old_version ~= selected_version then
-- user clicked on other version while loading
return
end
local pack_id_elem_map = {}
pack_list.elements = {}
for i = 1, #packs do
local pack = packs[i]
if pack.game_version == selected_version then
local progress_bar = progress:new({
style = { background_color = { 0, 0, 0, 0 } },
})
local progress_collapse = collapse:new(progress_bar)
local channel_name = string.format("pack_download_progress_%d_%s", pack.game_version, pack.folder_name)
channel_callbacks.register(channel_name, function(percent)
progress_bar.percentage = percent
progress_collapse:toggle(true)
end)
local elem = quad:new({
child_element = flex:new({
label:new(pack.name, { wrap = true }),
progress_collapse,
}, { direction = "column", align_items = "stretch", align_relative_to = "parentparent" }),
selectable = true,
click_handler = function(self)
self.download_promise = async(function()
ongoing_downloads[pack.game_version] = ongoing_downloads[pack.game_version] or {}
if ongoing_downloads[pack.game_version][pack.folder_name] then
-- download already in progress
return
end
ongoing_downloads[pack.game_version][pack.folder_name] = true
local promises = {}
for j = 1, #pack.dependency_ids do
local elem = pack_id_elem_map[pack.dependency_ids[j]]
-- element may not exist if pack is already downloaded
if elem then
if elem.download_promise then
-- download is in progress
promises[#promises + 1] = elem.download_promise
else
-- download is started
promises[#promises + 1] = elem.click_handler(elem)
end
end
end
local ret = async.await(download.get(pack.game_version, pack.folder_name))
progress_collapse:toggle(false)
if ret then
ongoing_downloads[pack.game_version][pack.folder_name] = nil
progress_bar.percentage = 0
dialogs.alert(ret)
return
end
log("Waiting for dependency packs...")
for j = 1, #promises do
async.await(promises[j])
end
local pack_data = async.await(game_handler.import_pack(pack.folder_name, pack.game_version))
local elem = pack_elements.make_pack_element(pack_data, true)
-- element may not be created if an element for the pack already exists
local current_chunk = 0
local chunk_size = 10
local loading_in_progress = false

local load_pack_chunk = async(function()
loading_in_progress = true
pack_list.elements[#pack_list.elements] = nil
local start = current_chunk * chunk_size + 1
current_chunk = current_chunk + 1
local stop = current_chunk * chunk_size
local new_packs = async.await(download.get_pack_list(start, stop))
local new_elem
for i = 1, #new_packs do
local pack = new_packs[i]
local progress_bar = progress:new({
style = { background_color = { 0, 0, 0, 0 } },
})
local progress_collapse = collapse:new(progress_bar)
local channel_name = string.format("pack_download_progress_%d_%s", pack.game_version, pack.folder_name)
channel_callbacks.register(channel_name, function(percent)
progress_bar.percentage = percent
progress_collapse:toggle(true)
end)
local elem = quad:new({
child_element = flex:new({
label:new(pack.name, { wrap = true }),
progress_collapse,
}, { direction = "column", align_items = "stretch", align_relative_to = "parentparent" }),
selectable = true,
click_handler = function(self)
self.download_promise = async(function()
ongoing_downloads[pack.game_version] = ongoing_downloads[pack.game_version] or {}
if ongoing_downloads[pack.game_version][pack.folder_name] then
-- download already in progress
return
end
ongoing_downloads[pack.game_version][pack.folder_name] = true
local promises = {}
for j = 1, #pack.dependency_ids do
local elem = pack_id_elem_map[pack.dependency_ids[j]]
-- element may not exist if pack is already downloaded
if elem then
require("ui.screens.levelselect").state.packs:mutated(false)
elem:update_size()
elem:click(false)
if elem.download_promise then
-- download is in progress
promises[#promises + 1] = elem.download_promise
else
-- download is started
promises[#promises + 1] = elem.click_handler(elem)
end
end
table.remove(pack_list.elements, self.parent_index)
pack_list:mutated(false)
require("ui.elements.element").update_size(pack_list)
end
local ret = async.await(download.get(pack.game_version, pack.folder_name))
progress_collapse:toggle(false)
if ret then
ongoing_downloads[pack.game_version][pack.folder_name] = nil
end)()
return self.download_promise
end,
})
pack_list.elements[#pack_list.elements + 1] = elem
pack_id_elem_map[pack.id] = elem
end
progress_bar.percentage = 0
dialogs.alert(ret)
return
end
log("Waiting for dependency packs...")
for j = 1, #promises do
async.await(promises[j])
end
local pack_data = async.await(game_handler.import_pack(pack.folder_name, pack.game_version))
local elem = pack_elements.make_pack_element(pack_data, true)
-- element may not be created if an element for the pack already exists
if elem then
require("ui.screens.levelselect").state.packs:mutated(false)
elem:update_size()
elem:click(false)
end
table.remove(pack_list.elements, self.parent_index)
pack_list:mutated(false)
require("ui.elements.element").update_size(pack_list)
ongoing_downloads[pack.game_version][pack.folder_name] = nil
end)()
return self.download_promise
end,
})
pack_list.elements[#pack_list.elements + 1] = elem
pack_id_elem_map[pack.id] = elem
new_elem = elem
end
pack_list:mutated(false)
if pack_list.elements[1] then
if new_elem then
pack_list.elements[#pack_list.elements] = loading
pack_list:mutated(false)
new_elem:update_size()
elseif #pack_list.elements > 0 then
pack_list.elements[1]:update_size()
end
loading_in_progress = false
end)

local function make_version_button(version)
local background_color = { 0, 0, 0, 1 }
if selected_version == version then
background_color = { 0, 1, 1, 1 }
end
return quad:new({
child_element = label:new(tostring(version)),
selectable = true,
click_handler = function(self)
for i = 1, #version_buttons do
version_buttons[i].background_color = { 0, 0, 0, 1 }
end
self.background_color = { 0, 1, 1, 1 }
selected_version = version
create_pack_list()
end,
style = { background_color = background_color },
})
end

version_buttons = {
make_version_button(21),
make_version_button(20),
make_version_button(192),
}

local pack_scroll
pack_scroll = scroll:new(pack_list, {
change_handler = async(function()
if loading.y < pack_scroll.height then
async.await(load_pack_chunk())
end
end),
})
pack_overlay.layout = quad:new({
child_element = flex:new({
flex:new({
flex:new(version_buttons),
label:new("All packs"),
quad:new({
child_element = icon:new("x-lg"),
selectable = true,
Expand All @@ -154,10 +142,14 @@ pack_overlay.layout = quad:new({
end,
}),
}, { justify_content = "between" }),
scroll:new(pack_list),
pack_scroll,
}, { direction = "column" }),
})
pack_overlay.transition = transitions.slide
pack_overlay.onopen = create_pack_list
pack_overlay.onopen = function()
if current_chunk == 0 and not loading_in_progress then
load_pack_chunk()
end
end

return pack_overlay

0 comments on commit c2e2e01

Please sign in to comment.