Async count updates

This commit is contained in:
Max
2026-06-01 15:10:15 +02:00
parent 0c33acf06d
commit 514c7e9b22
+146 -26
View File
@@ -53,6 +53,8 @@ local fallbackIcon = false
local backButton = false
local scrollUpButton = false
local scrollDownButton = false
local overviewCachedCounts = {}
local overviewCachedSortedItemIds = nil
local overviewScrollCurrentRow = 0
local overviewScrollTargetRow = 0
local drawOverview
@@ -330,6 +332,42 @@ local function getMeItemCounts(itemIds)
return counts
end
local function makeZeroCounts(itemIds)
local counts = {}
for i = 1, #itemIds do
counts[itemIds[i]] = 0
end
return counts
end
local function createAsyncMeItemCountsJob(itemIds, batchSize)
local counts = makeZeroCounts(itemIds)
local index = 1
batchSize = math.max(1, math.floor(tonumber(batchSize) or 1))
return {
step = function()
local bridge = ensureStorageBridge()
if not bridge then
return true, counts
end
local lastIndex = math.min(#itemIds, index + batchSize - 1)
for i = index, lastIndex do
counts[itemIds[i]] = getMeItemCount(itemIds[i])
end
index = lastIndex + 1
return index > #itemIds, counts
end,
}
end
local function getFallbackIcon()
if fallbackIcon == false then
fallbackIcon = parseNfpImage(table.concat({
@@ -566,8 +604,8 @@ local function drawItem(img, cellX, cellY, count, offsetY)
end
local function runScrollableGrid(options)
local entries = {}
local counts = {}
local entries = options.getInitialEntries()
local counts = options.getInitialCounts(entries)
local visibleItemCount = 0
local totalRows = 0
local maxScrollRow = 0
@@ -575,6 +613,9 @@ local function runScrollableGrid(options)
local targetScrollRow = 0
local refreshTimer
local animationTimer
local refreshJob
local refreshJobTimer
local queuedRefresh = false
local columns = 3
local rowsPerView = 3
@@ -645,8 +686,19 @@ local function runScrollableGrid(options)
end
end
local function refreshGridData()
entries, counts = options.getEntriesAndCounts()
local function startRefreshJob()
if refreshJob then
return false
end
refreshJob = options.createRefreshJob(entries, counts)
if not refreshJob then
return false
end
refreshJobTimer = os.startTimer(options.refreshStepSeconds or 0.05)
return true
end
local function renderGrid()
@@ -704,18 +756,41 @@ local function runScrollableGrid(options)
frame:drawBuffer()
end
refreshGridData()
renderGrid()
startRefreshJob()
refreshTimer = os.startTimer(options.refreshSeconds or 30)
while true do
local event, p1, x, y = os.pullEvent()
if event == "timer" and p1 == refreshTimer then
refreshGridData()
renderGrid()
if refreshJob then
queuedRefresh = true
else
startRefreshJob()
end
refreshTimer = os.startTimer(options.refreshSeconds or 30)
scheduleAnimation()
elseif event == "timer" and p1 == refreshJobTimer then
local isDone, newEntries, newCounts = refreshJob.step()
if isDone then
refreshJob = nil
refreshJobTimer = nil
if newEntries and newCounts then
entries = newEntries
counts = newCounts
renderGrid()
end
if queuedRefresh then
queuedRefresh = false
startRefreshJob()
end
else
refreshJobTimer = os.startTimer(options.refreshStepSeconds or 0.05)
end
elseif event == "timer" and p1 == animationTimer then
local delta = targetScrollRow - currentScrollRow
@@ -799,8 +874,26 @@ local function drawPage(base_id)
runScrollableGrid({
refreshSeconds = 5,
getEntriesAndCounts = function()
return pageItems, getMeItemCounts(pageItemIds)
getInitialEntries = function()
return pageItems
end,
getInitialCounts = function()
return makeZeroCounts(pageItemIds)
end,
createRefreshJob = function(currentEntries)
local job = createAsyncMeItemCountsJob(pageItemIds, 3)
return {
step = function()
local isDone, itemCounts = job.step()
if isDone then
return true, currentEntries, itemCounts
end
return false
end,
}
end,
getId = function(entry)
return entry.id
@@ -829,8 +922,39 @@ drawOverview = function()
local items = getBaseItemIds()
local defaultIcon = getFallbackIcon()
local function sortOverviewItems(itemCounts)
local sortedItemIds = {}
for i = 1, #items do
sortedItemIds[i] = items[i]
end
table.sort(sortedItemIds, function(a, b)
local countA = itemCounts[a] or 0
local countB = itemCounts[b] or 0
if countA ~= countB then
return countA > countB
end
return a < b
end)
return sortedItemIds
end
runScrollableGrid({
refreshSeconds = 30,
getInitialEntries = function()
if overviewCachedSortedItemIds and #overviewCachedSortedItemIds > 0 then
return overviewCachedSortedItemIds
end
return sortOverviewItems(overviewCachedCounts)
end,
getInitialCounts = function()
return overviewCachedCounts
end,
getInitialScrollState = function()
return overviewScrollCurrentRow, overviewScrollTargetRow
end,
@@ -838,26 +962,22 @@ drawOverview = function()
overviewScrollCurrentRow = currentRow
overviewScrollTargetRow = targetRow
end,
getEntriesAndCounts = function()
local itemCounts = getMeItemCounts(items)
local sortedItemIds = {}
createRefreshJob = function()
local job = createAsyncMeItemCountsJob(items, 6)
for i = 1, #items do
sortedItemIds[i] = items[i]
end
return {
step = function()
local isDone, itemCounts = job.step()
table.sort(sortedItemIds, function(a, b)
local countA = itemCounts[a] or 0
local countB = itemCounts[b] or 0
if isDone then
overviewCachedCounts = itemCounts
overviewCachedSortedItemIds = sortOverviewItems(overviewCachedCounts)
return true, overviewCachedSortedItemIds, overviewCachedCounts
end
if countA ~= countB then
return countA > countB
end
return a < b
end)
return sortedItemIds, itemCounts
return false
end,
}
end,
getId = function(entry)
return entry