diff --git a/spec/System/TestBuildListHelpers_spec.lua b/spec/System/TestBuildListHelpers_spec.lua index 40f48bbeac5..e7bd91dd09d 100644 --- a/spec/System/TestBuildListHelpers_spec.lua +++ b/spec/System/TestBuildListHelpers_spec.lua @@ -2,6 +2,7 @@ describe("BuildListHelpers", function() local originalBuildPath local originalCloudErrorPopup local originalFileSearch + local originalFilterBuildList local originalOpen local buildListHelpers local fileHeaders @@ -14,6 +15,7 @@ describe("BuildListHelpers", function() originalBuildPath = main.buildPath originalCloudErrorPopup = main.OpenCloudErrorPopup originalFileSearch = _G.NewFileSearch + originalFilterBuildList = main.filterBuildList originalOpen = io.open buildListHelpers = LoadModule("Modules/BuildListHelpers") fileHeaders = { } @@ -22,6 +24,7 @@ describe("BuildListHelpers", function() searchCount = 0 cloudErrorPath = nil main.buildPath = "Builds/" + main.filterBuildList = "" main.OpenCloudErrorPopup = function(_, path) cloudErrorPath = path end @@ -53,6 +56,7 @@ describe("BuildListHelpers", function() main.buildPath = originalBuildPath main.OpenCloudErrorPopup = originalCloudErrorPopup _G.NewFileSearch = originalFileSearch + main.filterBuildList = originalFilterBuildList io.open = originalOpen end) @@ -77,6 +81,33 @@ describe("BuildListHelpers", function() assert.are.same(opensAfterIndex, fileOpenCount) end) + it("refreshes only the reopened build when returning to the build list", function() + searches["files:Builds/*.xml"] = { { name = "Root.xml", modified = 1 } } + searches["folders:Builds/*"] = { { name = "League", modified = 2 } } + searches["files:Builds/League/*.xml"] = { { name = "Nested.xml", modified = 3 } } + fileHeaders["Builds/Root.xml"] = '' + fileHeaders["Builds/League/Nested.xml"] = '' + local listMode = require("Modules.BuildList") + + listMode:Init() + local scansAfterIndex = searchCount + local opensAfterIndex = fileOpenCount + searches["files:Builds/Root.xml"] = { { name = "Root.xml", modified = 4 } } + fileHeaders["Builds/Root.xml"] = '' + listMode:Init("Root", "") + + assert.are.same(scansAfterIndex + 1, searchCount) + assert.are.same(opensAfterIndex + 1, fileOpenCount) + assert.are.same(81, listMode.controls.buildList.selValue.level) + assert.are.same("Assassin", listMode.controls.buildList.selValue.ascendClassName) + assert.are.same(4, listMode.controls.buildList.selValue.modified) + + local scansBeforeFolderChange = searchCount + listMode:Init("Nested", "League/") + assert.are.same(scansBeforeFolderChange + 2, searchCount) + assert.are.same("Builds/League/Nested.xml", listMode.controls.buildList.selValue.fullFileName) + end) + it("reports cloud read failures", function() searches["files:Builds/*.xml"] = { { name = "Cloud.xml" } } fileHeaders["Builds/Cloud.xml"] = false diff --git a/src/Modules/BuildList.lua b/src/Modules/BuildList.lua index 7648110d0ce..053b2f02594 100644 --- a/src/Modules/BuildList.lua +++ b/src/Modules/BuildList.lua @@ -14,6 +14,8 @@ local listMode = new("ControlHost"):ControlHost() function listMode:Init(selBuildName, subPath) if self.initialised then + local subPathChanged = subPath and subPath ~= self.subPath + local reuseBuildIndex = not subPathChanged and self.indexedBuildPath == main.buildPath self.subPath = subPath or self.subPath self.controls.buildList.controls.path:SetSubPath(self.subPath) --if main.showPublicBuilds then @@ -22,7 +24,14 @@ function listMode:Init(selBuildName, subPath) else self.controls.ExtBuildList = nil end - self:BuildList() + if reuseBuildIndex then + if selBuildName then + buildListHelpers.RefreshBuild(self.buildIndex, self.subPath, selBuildName..".xml") + end + self:FilterBuildList() + elseif not subPathChanged then + self:BuildList() + end self.controls.buildList:SelByFullFileName(selBuildName and main.buildPath..self.subPath..selBuildName..".xml") self:SelectControl(self.controls.buildList) return @@ -199,6 +208,7 @@ function listMode:GetDestName(subPath, fileName) end function listMode:BuildList() + self.indexedBuildPath = main.buildPath self.buildIndex = buildListHelpers.ScanFolder(self.subPath) self:FilterBuildList() end diff --git a/src/Modules/BuildListHelpers.lua b/src/Modules/BuildListHelpers.lua index b6fb906d28c..dc1ff177a0d 100644 --- a/src/Modules/BuildListHelpers.lua +++ b/src/Modules/BuildListHelpers.lua @@ -34,6 +34,22 @@ local function ReadBuildHeader(fullFileName) } end +local function ReadBuild(subPath, fileName, modified) + local fullFileName = main.buildPath..subPath..fileName + local header = ReadBuildHeader(fullFileName) + if not header then return end + return { + fileName = fileName, + subPath = subPath, + fullFileName = fullFileName, + modified = modified, + buildName = fileName:gsub("%.xml$",""), + level = header.level, + className = header.className, + ascendClassName = header.ascendClassName, + } +end + local function MatchEntry(entry, terms) for _, term in ipairs(terms) do local termLower = term:lower() @@ -66,19 +82,9 @@ local function ScanFolder(subPath) local handle = NewFileSearch(main.buildPath..currentSubPath.."*.xml") while handle do local fileName = handle:GetFileName() - local fullFileName = main.buildPath..currentSubPath..fileName - local header = ReadBuildHeader(fullFileName) - if header then - t_insert(list, { - fileName = fileName, - subPath = currentSubPath, - fullFileName = fullFileName, - modified = handle:GetFileModifiedTime(), - buildName = fileName:gsub("%.xml$",""), - level = header.level, - className = header.className, - ascendClassName = header.ascendClassName, - }) + local build = ReadBuild(currentSubPath, fileName, handle:GetFileModifiedTime()) + if build then + t_insert(list, build) end if not handle:NextFile() then break end @@ -110,6 +116,27 @@ local function ScanFolder(subPath) return list end +local function RefreshBuild(index, subPath, fileName) + local fullFileName = main.buildPath..subPath..fileName + local handle = NewFileSearch(fullFileName) + local build = handle and ReadBuild(subPath, fileName, handle:GetFileModifiedTime()) + if handle and not build then return end + + for buildIndex, entry in ipairs(index) do + if entry.fullFileName == fullFileName then + if build then + index[buildIndex] = build + else + table.remove(index, buildIndex) + end + return + end + end + if build then + t_insert(index, build) + end +end + -- Filtering the cached index avoids filesystem work on every keystroke. local function FilterList(index, subPath, filterText) local terms = { } @@ -196,6 +223,7 @@ return { buildSortDropList = buildSortDropList, CanMoveToSubPath = CanMoveToSubPath, FilterList = FilterList, + RefreshBuild = RefreshBuild, ScanFolder = ScanFolder, SortList = SortList, }