-- ------------------------------------------------------------------------------ -- -- TradeSkillMaster -- -- https://tradeskillmaster.com -- -- All Rights Reserved - Detailed license information included with addon. -- -- ------------------------------------------------------------------------------ -- local _, TSM = ... local SavedSearches = TSM.Auctioning:NewPackage("SavedSearches") local L = TSM.Include("Locale").GetTable() local Log = TSM.Include("Util.Log") local String = TSM.Include("Util.String") local Database = TSM.Include("Util.Database") local TempTable = TSM.Include("Util.TempTable") local Theme = TSM.Include("Util.Theme") local Settings = TSM.Include("Service.Settings") local private = { settings = nil, db = nil, } local FILTER_SEP = "\001" local MAX_RECENT_SEARCHES = 500 -- ============================================================================ -- Module Functions -- ============================================================================ function SavedSearches.OnInitialize() private.settings = Settings.NewView() :AddKey("global", "userData", "savedAuctioningSearches") -- remove duplicates local seen = TempTable.Acquire() for i = #private.settings.savedAuctioningSearches.filters, 1, -1 do local filter = private.settings.savedAuctioningSearches.filters[i] if seen[filter] then tremove(private.settings.savedAuctioningSearches.filters, i) tremove(private.settings.savedAuctioningSearches.searchTypes, i) private.settings.savedAuctioningSearches.name[filter] = nil private.settings.savedAuctioningSearches.isFavorite[filter] = nil else seen[filter] = true end end TempTable.Release(seen) -- remove old recent searches local remainingRecentSearches = MAX_RECENT_SEARCHES local numRemoved = 0 for i = #private.settings.savedAuctioningSearches.filters, 1, -1 do local filter = private.settings.savedAuctioningSearches.filters if not private.settings.savedAuctioningSearches.isFavorite[filter] then if remainingRecentSearches > 0 then remainingRecentSearches = remainingRecentSearches - 1 else tremove(private.settings.savedAuctioningSearches.filters, i) tremove(private.settings.savedAuctioningSearches.searchTypes, i) private.settings.savedAuctioningSearches.name[filter] = nil private.settings.savedAuctioningSearches.isFavorite[filter] = nil numRemoved = numRemoved + 1 end end end if numRemoved > 0 then Log.Info("Removed %d old recent searches", numRemoved) end private.db = Database.NewSchema("AUCTIONING_SAVED_SEARCHES") :AddUniqueNumberField("index") :AddBooleanField("isFavorite") :AddStringField("searchType") :AddStringField("filter") :AddStringField("name") :AddIndex("index") :Commit() private.RebuildDB() end function SavedSearches.CreateRecentSearchesQuery() return private.db:NewQuery() :OrderBy("index", false) end function SavedSearches.CreateFavoriteSearchesQuery() return private.db:NewQuery() :Equal("isFavorite", true) :OrderBy("name", true) end function SavedSearches.SetSearchIsFavorite(dbRow, isFavorite) local filter = dbRow:GetField("filter") private.settings.savedAuctioningSearches.isFavorite[filter] = isFavorite or nil dbRow:SetField("isFavorite", isFavorite) :Update() end function SavedSearches.RenameSearch(dbRow, newName) local filter = dbRow:GetField("filter") private.settings.savedAuctioningSearches.name[filter] = newName dbRow:SetField("name", newName) :Update() end function SavedSearches.DeleteSearch(dbRow) local index, filter = dbRow:GetFields("index", "filter") tremove(private.settings.savedAuctioningSearches.filters, index) tremove(private.settings.savedAuctioningSearches.searchTypes, index) private.settings.savedAuctioningSearches.name[filter] = nil private.settings.savedAuctioningSearches.isFavorite[filter] = nil private.RebuildDB() end function SavedSearches.RecordSearch(searchList, searchType) assert(searchType == "postItems" or searchType == "postGroups" or searchType == "cancelGroups") local filter = table.concat(searchList, FILTER_SEP) for i, existingFilter in ipairs(private.settings.savedAuctioningSearches.filters) do local existingSearchType = private.settings.savedAuctioningSearches.searchTypes[i] if filter == existingFilter and searchType == existingSearchType then -- move this to the end of the list and rebuild the DB -- insert the existing filter so we don't need to update the isFavorite and name tables tremove(private.settings.savedAuctioningSearches.filters, i) tinsert(private.settings.savedAuctioningSearches.filters, existingFilter) tremove(private.settings.savedAuctioningSearches.searchTypes, i) tinsert(private.settings.savedAuctioningSearches.searchTypes, existingSearchType) private.RebuildDB() return end end -- didn't find an existing entry, so add a new one tinsert(private.settings.savedAuctioningSearches.filters, filter) tinsert(private.settings.savedAuctioningSearches.searchTypes, searchType) assert(#private.settings.savedAuctioningSearches.filters == #private.settings.savedAuctioningSearches.searchTypes) private.db:NewRow() :SetField("index", #private.settings.savedAuctioningSearches.filters) :SetField("isFavorite", false) :SetField("searchType", searchType) :SetField("filter", filter) :SetField("name", private.GetSearchName(filter, searchType)) :Create() end function SavedSearches.FiltersToTable(dbRow, tbl) String.SafeSplit(dbRow:GetField("filter"), FILTER_SEP, tbl) end -- ============================================================================ -- Private Helper Functions -- ============================================================================ function private.RebuildDB() assert(#private.settings.savedAuctioningSearches.filters == #private.settings.savedAuctioningSearches.searchTypes) private.db:TruncateAndBulkInsertStart() for index, filter in ipairs(private.settings.savedAuctioningSearches.filters) do local searchType = private.settings.savedAuctioningSearches.searchTypes[index] assert(searchType == "postItems" or searchType == "postGroups" or searchType == "cancelGroups") local name = private.settings.savedAuctioningSearches.name[filter] or private.GetSearchName(filter, searchType) local isFavorite = private.settings.savedAuctioningSearches.isFavorite[filter] and true or false private.db:BulkInsertNewRow(index, isFavorite, searchType, filter, name) end private.db:BulkInsertEnd() end function private.GetSearchName(filter, searchType) local filters = TempTable.Acquire() local searchTypeStr, numFiltersStr = nil, nil if filter == "" or string.sub(filter, 1, 1) == FILTER_SEP then tinsert(filters, L["Base Group"]) end if searchType == "postGroups" or searchType == "cancelGroups" then for groupPath in gmatch(filter, "[^"..FILTER_SEP.."]+") do local groupName = TSM.Groups.Path.GetName(groupPath) local level = select('#', strsplit(TSM.CONST.GROUP_SEP, groupPath)) local color = Theme.GetGroupColor(level) tinsert(filters, color:ColorText(groupName)) end searchTypeStr = searchType == "postGroups" and L["Post Scan"] or L["Cancel Scan"] numFiltersStr = #filters == 1 and L["1 Group"] or format(L["%d Groups"], #filters) elseif searchType == "postItems" then local numItems = 0 for itemString in gmatch(filter, "[^"..FILTER_SEP.."]+") do numItems = numItems + 1 local coloredName = TSM.UI.GetColoredItemName(itemString) if coloredName then tinsert(filters, coloredName) end end searchTypeStr = L["Post Scan"] numFiltersStr = numItems == 1 and L["1 Item"] or format(L["%d Items"], numItems) else error("Unknown searchType: "..tostring(searchType)) end local groupList = nil if #filters > 10 then groupList = table.concat(filters, ", ", 1, 10)..",..." TempTable.Release(filters) else groupList = strjoin(", ", TempTable.UnpackAndRelease(filters)) end return format("%s (%s): %s", searchTypeStr, numFiltersStr, groupList) end