Async count updates
This commit is contained in:
+146
-26
@@ -53,6 +53,8 @@ local fallbackIcon = false
|
|||||||
local backButton = false
|
local backButton = false
|
||||||
local scrollUpButton = false
|
local scrollUpButton = false
|
||||||
local scrollDownButton = false
|
local scrollDownButton = false
|
||||||
|
local overviewCachedCounts = {}
|
||||||
|
local overviewCachedSortedItemIds = nil
|
||||||
local overviewScrollCurrentRow = 0
|
local overviewScrollCurrentRow = 0
|
||||||
local overviewScrollTargetRow = 0
|
local overviewScrollTargetRow = 0
|
||||||
local drawOverview
|
local drawOverview
|
||||||
@@ -330,6 +332,42 @@ local function getMeItemCounts(itemIds)
|
|||||||
return counts
|
return counts
|
||||||
end
|
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()
|
local function getFallbackIcon()
|
||||||
if fallbackIcon == false then
|
if fallbackIcon == false then
|
||||||
fallbackIcon = parseNfpImage(table.concat({
|
fallbackIcon = parseNfpImage(table.concat({
|
||||||
@@ -566,8 +604,8 @@ local function drawItem(img, cellX, cellY, count, offsetY)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function runScrollableGrid(options)
|
local function runScrollableGrid(options)
|
||||||
local entries = {}
|
local entries = options.getInitialEntries()
|
||||||
local counts = {}
|
local counts = options.getInitialCounts(entries)
|
||||||
local visibleItemCount = 0
|
local visibleItemCount = 0
|
||||||
local totalRows = 0
|
local totalRows = 0
|
||||||
local maxScrollRow = 0
|
local maxScrollRow = 0
|
||||||
@@ -575,6 +613,9 @@ local function runScrollableGrid(options)
|
|||||||
local targetScrollRow = 0
|
local targetScrollRow = 0
|
||||||
local refreshTimer
|
local refreshTimer
|
||||||
local animationTimer
|
local animationTimer
|
||||||
|
local refreshJob
|
||||||
|
local refreshJobTimer
|
||||||
|
local queuedRefresh = false
|
||||||
|
|
||||||
local columns = 3
|
local columns = 3
|
||||||
local rowsPerView = 3
|
local rowsPerView = 3
|
||||||
@@ -645,8 +686,19 @@ local function runScrollableGrid(options)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local function refreshGridData()
|
local function startRefreshJob()
|
||||||
entries, counts = options.getEntriesAndCounts()
|
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
|
end
|
||||||
|
|
||||||
local function renderGrid()
|
local function renderGrid()
|
||||||
@@ -704,18 +756,41 @@ local function runScrollableGrid(options)
|
|||||||
frame:drawBuffer()
|
frame:drawBuffer()
|
||||||
end
|
end
|
||||||
|
|
||||||
refreshGridData()
|
|
||||||
renderGrid()
|
renderGrid()
|
||||||
|
startRefreshJob()
|
||||||
refreshTimer = os.startTimer(options.refreshSeconds or 30)
|
refreshTimer = os.startTimer(options.refreshSeconds or 30)
|
||||||
|
|
||||||
while true do
|
while true do
|
||||||
local event, p1, x, y = os.pullEvent()
|
local event, p1, x, y = os.pullEvent()
|
||||||
|
|
||||||
if event == "timer" and p1 == refreshTimer then
|
if event == "timer" and p1 == refreshTimer then
|
||||||
refreshGridData()
|
if refreshJob then
|
||||||
renderGrid()
|
queuedRefresh = true
|
||||||
|
else
|
||||||
|
startRefreshJob()
|
||||||
|
end
|
||||||
refreshTimer = os.startTimer(options.refreshSeconds or 30)
|
refreshTimer = os.startTimer(options.refreshSeconds or 30)
|
||||||
scheduleAnimation()
|
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
|
elseif event == "timer" and p1 == animationTimer then
|
||||||
local delta = targetScrollRow - currentScrollRow
|
local delta = targetScrollRow - currentScrollRow
|
||||||
|
|
||||||
@@ -799,8 +874,26 @@ local function drawPage(base_id)
|
|||||||
|
|
||||||
runScrollableGrid({
|
runScrollableGrid({
|
||||||
refreshSeconds = 5,
|
refreshSeconds = 5,
|
||||||
getEntriesAndCounts = function()
|
getInitialEntries = function()
|
||||||
return pageItems, getMeItemCounts(pageItemIds)
|
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,
|
end,
|
||||||
getId = function(entry)
|
getId = function(entry)
|
||||||
return entry.id
|
return entry.id
|
||||||
@@ -829,8 +922,39 @@ drawOverview = function()
|
|||||||
local items = getBaseItemIds()
|
local items = getBaseItemIds()
|
||||||
local defaultIcon = getFallbackIcon()
|
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({
|
runScrollableGrid({
|
||||||
refreshSeconds = 30,
|
refreshSeconds = 30,
|
||||||
|
getInitialEntries = function()
|
||||||
|
if overviewCachedSortedItemIds and #overviewCachedSortedItemIds > 0 then
|
||||||
|
return overviewCachedSortedItemIds
|
||||||
|
end
|
||||||
|
|
||||||
|
return sortOverviewItems(overviewCachedCounts)
|
||||||
|
end,
|
||||||
|
getInitialCounts = function()
|
||||||
|
return overviewCachedCounts
|
||||||
|
end,
|
||||||
getInitialScrollState = function()
|
getInitialScrollState = function()
|
||||||
return overviewScrollCurrentRow, overviewScrollTargetRow
|
return overviewScrollCurrentRow, overviewScrollTargetRow
|
||||||
end,
|
end,
|
||||||
@@ -838,26 +962,22 @@ drawOverview = function()
|
|||||||
overviewScrollCurrentRow = currentRow
|
overviewScrollCurrentRow = currentRow
|
||||||
overviewScrollTargetRow = targetRow
|
overviewScrollTargetRow = targetRow
|
||||||
end,
|
end,
|
||||||
getEntriesAndCounts = function()
|
createRefreshJob = function()
|
||||||
local itemCounts = getMeItemCounts(items)
|
local job = createAsyncMeItemCountsJob(items, 6)
|
||||||
local sortedItemIds = {}
|
|
||||||
|
|
||||||
for i = 1, #items do
|
return {
|
||||||
sortedItemIds[i] = items[i]
|
step = function()
|
||||||
end
|
local isDone, itemCounts = job.step()
|
||||||
|
|
||||||
table.sort(sortedItemIds, function(a, b)
|
if isDone then
|
||||||
local countA = itemCounts[a] or 0
|
overviewCachedCounts = itemCounts
|
||||||
local countB = itemCounts[b] or 0
|
overviewCachedSortedItemIds = sortOverviewItems(overviewCachedCounts)
|
||||||
|
return true, overviewCachedSortedItemIds, overviewCachedCounts
|
||||||
|
end
|
||||||
|
|
||||||
if countA ~= countB then
|
return false
|
||||||
return countA > countB
|
end,
|
||||||
end
|
}
|
||||||
|
|
||||||
return a < b
|
|
||||||
end)
|
|
||||||
|
|
||||||
return sortedItemIds, itemCounts
|
|
||||||
end,
|
end,
|
||||||
getId = function(entry)
|
getId = function(entry)
|
||||||
return entry
|
return entry
|
||||||
|
|||||||
Reference in New Issue
Block a user