From 4fdd2ea052a62f9c31de03a67533531f9fee2bd2 Mon Sep 17 00:00:00 2001 From: Vati Date: Sat, 28 Feb 2026 03:50:31 +0400 Subject: [PATCH] feat: merge categories --- Core/CategoryManager.lua | 68 ++++++++++++++++++++++++++++++---------- UI/SettingsPopup.lua | 36 +++++++++++++++++++++ 2 files changed, 87 insertions(+), 17 deletions(-) diff --git a/Core/CategoryManager.lua b/Core/CategoryManager.lua index b0618b3..57ee310 100644 --- a/Core/CategoryManager.lua +++ b/Core/CategoryManager.lua @@ -475,6 +475,11 @@ function CategoryManager:MigrateCategories() end end + -- Ensure savedEquipSetProps table exists + if not cats.savedEquipSetProps then + cats.savedEquipSetProps = {} + end + -- Migrate: Convert per-category itemOverrides arrays to flat map at categories level if not cats.itemOverrides then cats.itemOverrides = {} @@ -685,9 +690,14 @@ function CategoryManager:UpdateCategory(categoryId, definition) return false end - -- Preserve isBuiltIn flag - definition.isBuiltIn = cats.definitions[categoryId].isBuiltIn - cats.definitions[categoryId] = definition + -- Shallow merge: update existing definition with new fields + -- This preserves fields the caller didn't pass (group, priority, categoryMark, etc.) + local existing = cats.definitions[categoryId] + for k, v in pairs(definition) do + existing[k] = v + end + -- Always preserve isBuiltIn from original + existing.isBuiltIn = existing.isBuiltIn self:SaveCategories(cats) return true @@ -1277,9 +1287,8 @@ end -- Equipment Set Category Sync ------------------------------------------- --- Saved properties for equipment set categories that were user-edited --- Preserves user changes (enabled state, order position) when sets are deleted/recreated -local savedEquipSetProps = {} +-- Note: savedEquipSetProps is stored in cats.savedEquipSetProps (persisted in SavedVariables) +-- Preserves user changes (enabled state, group, mark, order position) when sets are deleted/recreated -- Sync equipment set categories with current set data from EquipmentSets module function CategoryManager:SyncEquipmentSetCategories() @@ -1295,6 +1304,11 @@ function CategoryManager:SyncEquipmentSetCategories() local cats = self:GetCategories() local existingSetCats = {} + -- Ensure savedEquipSetProps table exists (persisted in SavedVariables) + if not cats.savedEquipSetProps then + cats.savedEquipSetProps = {} + end + -- Find existing EquipSet categories for id, def in pairs(cats.definitions) do if string.find(id, "^EquipSet:") then @@ -1307,29 +1321,38 @@ function CategoryManager:SyncEquipmentSetCategories() local catId = "EquipSet:" .. setName if not cats.definitions[catId] then -- Check for saved properties from a previously deleted set - local props = savedEquipSetProps[catId] + local props = cats.savedEquipSetProps[catId] local defaultMark = "Interface\\AddOns\\Guda\\Assets\\equipment" local newDef = { name = setName, icon = "Interface\\Icons\\INV_Chest_Chain_04", rules = {}, matchMode = "all", - priority = 65, + priority = props and props.priority or 65, enabled = props and props.enabled or true, isBuiltIn = false, isEquipSetCategory = true, - group = GROUP_MAIN, + group = props and props.group or GROUP_MAIN, categoryMark = props and props.categoryMark or defaultMark, } cats.definitions[catId] = newDef - -- Add to order + -- Restore saved order position or insert at end of Main group local insertPos = nil - for i = table.getn(cats.order), 1, -1 do - local existDef = cats.definitions[cats.order[i]] - if existDef and (existDef.group or GROUP_MAIN) == GROUP_MAIN then - insertPos = i + 1 - break + if props and props.orderPos then + -- Clamp to valid range + insertPos = props.orderPos + if insertPos > table.getn(cats.order) + 1 then + insertPos = table.getn(cats.order) + 1 + end + end + if not insertPos then + for i = table.getn(cats.order), 1, -1 do + local existDef = cats.definitions[cats.order[i]] + if existDef and (existDef.group or GROUP_MAIN) == GROUP_MAIN then + insertPos = i + 1 + break + end end end if insertPos then @@ -1347,10 +1370,21 @@ function CategoryManager:SyncEquipmentSetCategories() for catId in pairs(existingSetCats) do local def = cats.definitions[catId] if def then - -- Save user-edited properties before deletion - savedEquipSetProps[catId] = { + -- Find current order position before removal + local orderPos = nil + for i, id in ipairs(cats.order) do + if id == catId then + orderPos = i + break + end + end + -- Save user-edited properties before deletion (persisted across reloads) + cats.savedEquipSetProps[catId] = { enabled = def.enabled, categoryMark = def.categoryMark, + group = def.group, + priority = def.priority, + orderPos = orderPos, } end cats.definitions[catId] = nil diff --git a/UI/SettingsPopup.lua b/UI/SettingsPopup.lua index 521e003..a92e205 100644 --- a/UI/SettingsPopup.lua +++ b/UI/SettingsPopup.lua @@ -1541,6 +1541,31 @@ local function GetCategoryRowFrame(index) builtInText:SetTextColor(0.5, 0.5, 0.5) row.builtInText = builtInText + -- Merge checkbox (shown on group header rows) + local mergeCheckbox = CreateFrame("CheckButton", rowName .. "_MergeCheckbox", row, "UICheckButtonTemplate") + mergeCheckbox:SetWidth(20) + mergeCheckbox:SetHeight(20) + mergeCheckbox:SetPoint("RIGHT", row, "RIGHT", -5, 0) + mergeCheckbox:SetScript("OnClick", function() + local groupName = this:GetParent().groupName + if groupName then + local mergedGroups = Guda.Modules.DB:GetSetting("mergedGroups") or {} + if this:GetChecked() == 1 then + mergedGroups[groupName] = true + else + mergedGroups[groupName] = nil + end + Guda.Modules.DB:SetSetting("mergedGroups", mergedGroups) + Guda_SettingsPopup_RefreshBagFrames() + end + end) + local mergeLabel = row:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall") + mergeLabel:SetPoint("RIGHT", mergeCheckbox, "LEFT", -2, 0) + mergeLabel:SetText("Merge") + mergeLabel:SetTextColor(0.8, 0.8, 0.8) + row.mergeCheckbox = mergeCheckbox + row.mergeLabel = mergeLabel + -- Hover highlight row:EnableMouse(true) row:SetScript("OnEnter", function() @@ -1602,6 +1627,7 @@ function Guda_SettingsPopup_CategoriesTab_Update() if entry.type == "header" then -- Show as group header row row.categoryId = nil + row.groupName = entry.groupName row.nameText:SetText("|cffffd100-- " .. entry.groupName .. " --|r") row.nameText:SetTextColor(1, 0.82, 0) row.checkbox:Hide() @@ -1610,15 +1636,25 @@ function Guda_SettingsPopup_CategoriesTab_Update() row.downBtn:Hide() row.deleteBtn:Hide() row.builtInText:Hide() + + -- Show merge checkbox for group headers + local mergedGroups = Guda.Modules.DB:GetSetting("mergedGroups") or {} + row.mergeCheckbox:SetChecked(mergedGroups[entry.groupName] and 1 or 0) + row.mergeCheckbox:Show() + row.mergeLabel:Show() + row:Show() elseif entry.type == "category" then local categoryId = entry.categoryId local categoryDef = entry.categoryDef row.categoryId = categoryId + row.groupName = nil row.nameText:SetText(categoryDef.name or categoryId) row.checkbox:Show() row.checkbox:SetChecked(categoryDef.enabled and 1 or 0) + row.mergeCheckbox:Hide() + row.mergeLabel:Hide() -- Show/hide delete button based on whether it's built-in if categoryDef.isBuiltIn then