Skip to content

Commit

Permalink
Add filtering by subcategory to GameBanana browser
Browse files Browse the repository at this point in the history
  • Loading branch information
maddie480 authored Jun 24, 2024
1 parent 33861a4 commit cc33d26
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 5 deletions.
2 changes: 1 addition & 1 deletion changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ and only contains the latest changes.
Its purpose is to be shown in Olympus when updating.

#changelog#
Use maddie480.ovh mirror instead of api.github.com for Lönn version listing, since GitHub has strict rate limits
Added filtering by subcategory to GameBanana browser
111 changes: 107 additions & 4 deletions src/scenes/gamebanana.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ local modinstaller = require("modinstaller")
local scene = {
name = "GameBanana",
sort = "latest",
itemtypeFilter = {}
itemtypeFilter = {},
subcategoryFilter = {}
}

local sortOptions = {
Expand Down Expand Up @@ -44,6 +45,79 @@ local function generateModColumns(self)
return lists
end

local function setGameBananaButtonVisible(visible)
local openGameBanana = scene.root:findChild("openGameBananaButton")
openGameBanana.visible = visible
openGameBanana.width = visible and -1 or 0
openGameBanana:reflow()
end

local function refreshSubcategories(itemtypeFilter)
-- Remove the old subcategory filter
scene.subcategoryFilter = {}
local oldSubcategoryFilter = scene.root:findChild("subcategoryFilter")
if oldSubcategoryFilter then
oldSubcategoryFilter:removeSelf()
end
setGameBananaButtonVisible(true)

-- If there is no category filter, we don't need a subcategory filter!
if not itemtypeFilter.itemtype then
return
end

threader.routine(function()
-- Fetch the subcategories of the category we are currently filtering on
local data, msg = threader.wrap("utils").downloadYAML("https://maddie480.ovh/celeste/gamebanana-subcategories"
.. "?itemtype=" .. itemtypeFilter.itemtype
.. (itemtypeFilter.categoryid and "&categoryId=" .. itemtypeFilter.categoryid or "")
):result()

if not data then
-- Error while calling the API
root:addChild(uie.paneled.row({
uie.label("Error downloading subcategories list: " .. tostring(msg)),
}):with({
clip = false,
cacheable = false
}):with(uiu.bottombound(16)):with(uiu.rightbound(16)):as("error"))
else
-- If there is no subcategory (only 1 entry which is presumably "All"), don't show the filter!
if #data <= 1 then
return
end

-- Convert the list retrieved from the API to a dropdown option list
local allTypes = {}
for _, category in ipairs(data) do
local categoryData = {}
if category.id then
categoryData["id"] = category.id
end

table.insert(allTypes, {
text = category.name .. (category.id and " (" .. category.count .. ")" or ""),
data = categoryData
})
end

-- Display the subcategory dropdown
local subcategoryFilter = uie.dropdown(
allTypes,
function(self, value)
if value ~= scene.subcategoryFilter then
scene.subcategoryFilter = value
setGameBananaButtonVisible(not value.id)
scene.loadPage(1)
end
end
):as("subcategoryFilter")

scene.root:findChild("subcategoryFilterZone"):addChild(subcategoryFilter)
end
end)
end


local root = uie.column({

Expand Down Expand Up @@ -139,11 +213,14 @@ local root = uie.column({
function(self, value)
if value ~= scene.itemtypeFilter then
scene.itemtypeFilter = value
refreshSubcategories(value)
scene.loadPage(1)
end
end
):as("itemtypeFilter"),

uie.row():as("subcategoryFilterZone"),

uie.field(
"",
function(self, value, prev)
Expand Down Expand Up @@ -210,7 +287,7 @@ function scene.loadPage(page)
end

scene.loadingPage = threader.routine(function()
local lists, pagePrev, pageLabel, pageNext, sortDropdown, itemtypeFilterDropdown = root:findChild("modColumns", "pagePrev", "pageLabel", "pageNext", "sort", "itemtypeFilter")
local lists, pagePrev, pageLabel, pageNext, sortDropdown, itemtypeFilterDropdown, subcategoryFilterDropdown = root:findChild("modColumns", "pagePrev", "pageLabel", "pageNext", "sort", "itemtypeFilter", "subcategoryFilter")

local errorPrev = root:findChild("error")
if errorPrev then
Expand Down Expand Up @@ -239,6 +316,12 @@ function scene.loadPage(page)
sortDropdown:reflow()
itemtypeFilterDropdown:reflow()

if subcategoryFilterDropdown then
subcategoryFilterDropdown.enabled = false
scene.root:findChild("subcategoryFilterZone").visible = not isQuery
subcategoryFilterDropdown:reflow()
end

if not isQuery then
if page == 0 then
pageLabel.text = "Featured"
Expand Down Expand Up @@ -268,7 +351,7 @@ function scene.loadPage(page)
if page == 0 then
entries, entriesError = scene.downloadFeaturedEntries()
else
entries, entriesError = scene.downloadSortedEntries(page, scene.sort, scene.itemtypeFilter)
entries, entriesError = scene.downloadSortedEntries(page, scene.sort, scene.itemtypeFilter, scene.subcategoryFilter)
end
else
entries, entriesError = scene.downloadSearchEntries(page)
Expand Down Expand Up @@ -296,6 +379,12 @@ function scene.loadPage(page)
pageNext:reflow()
sortDropdown:reflow()
itemtypeFilterDropdown:reflow()

if subcategoryFilterDropdown then
subcategoryFilterDropdown.enabled = not isQuery
subcategoryFilterDropdown:reflow()
end

return
end

Expand All @@ -314,6 +403,11 @@ function scene.loadPage(page)
pageNext:reflow()
sortDropdown:reflow()
itemtypeFilterDropdown:reflow()

if subcategoryFilterDropdown then
subcategoryFilterDropdown.enabled = not isQuery
subcategoryFilterDropdown:reflow()
end
end)
return scene.loadingPage
end
Expand Down Expand Up @@ -398,7 +492,7 @@ function scene.downloadSearchEntries(query)
return data, msg
end

function scene.downloadSortedEntries(page, sort, itemtypeFilter)
function scene.downloadSortedEntries(page, sort, itemtypeFilter, subcategoryFilter)
local url = string.format("https://maddie480.ovh/celeste/gamebanana-list?page=%s&sort=%s", page, sort)

-- apply optional filters
Expand All @@ -408,6 +502,15 @@ function scene.downloadSortedEntries(page, sort, itemtypeFilter)
if itemtypeFilter.categoryid then
url = url .. "&category=" .. itemtypeFilter.categoryid
end
if subcategoryFilter.id then
-- the hierarchy is itemtype > category > subcategory,
-- so the "subcategory" is actually the category if we are filtering on an itemtype
if itemtypeFilter.categoryid then
url = url .. "&subcategory=" .. subcategoryFilter.id
else
url = url .. "&category=" .. subcategoryFilter.id
end
end

local data = scene.cache[url]
if data ~= nil then
Expand Down

0 comments on commit cc33d26

Please sign in to comment.