From 99abfbe4ba65df2a09a01cec806d895d3541d945 Mon Sep 17 00:00:00 2001 From: Corey Ryan Dean Date: Mon, 18 May 2026 09:08:54 -0500 Subject: [PATCH] fix: preserve recent project history ordering --- src/Modules/Project Manager/RecentProjects.bb | 56 +++++++++++ src/Project Manager.bb | 26 ++---- src/Tests/Modules/RecentProjectsTest.bb | 93 +++++++++++++++++++ 3 files changed, 158 insertions(+), 17 deletions(-) create mode 100644 src/Modules/Project Manager/RecentProjects.bb create mode 100644 src/Tests/Modules/RecentProjectsTest.bb diff --git a/src/Modules/Project Manager/RecentProjects.bb b/src/Modules/Project Manager/RecentProjects.bb new file mode 100644 index 00000000..37bc393a --- /dev/null +++ b/src/Modules/Project Manager/RecentProjects.bb @@ -0,0 +1,56 @@ +Strict + +Function NormalizeProjectRoot$(rootDir$) + Local normalized$ = Replace$(rootDir$, "/", "\") + + While Len(normalized$) > 1 And Right$(normalized$, 1) = "\" + normalized$ = Left$(normalized$, Len(normalized$) - 1) + Wend + + Return Lower$(normalized$) +End Function + +Function RecentProjectsFindByRootDir%(recentProjects.BBList, rootDir$) + If recentProjects = Null Then Return -1 + + Local normalizedRoot$ = NormalizeProjectRoot$(rootDir$) + Local count = ListSize(recentProjects) - 1 + + For i = 0 To count + Local prj.Project = ListAt(recentProjects, i) + If NormalizeProjectRoot$(prj\rootDir) = normalizedRoot Then Return i + Next + + Return -1 +End Function + +Function RecentProjectsRemoveByRootDir(recentProjects.BBList, rootDir$) + If recentProjects = Null Then Return + + Local index = RecentProjectsFindByRootDir(recentProjects, rootDir$) + If index <> -1 Then ListRemove(recentProjects, index) +End Function + +Function RecentProjectsPromote(recentProjects.BBList, prj.Project) + If recentProjects = Null Or prj = Null Then Return + + RecentProjectsRemoveByRootDir(recentProjects, prj\rootDir) + ListAdd(recentProjects, prj) + + Local lastIndex = ListSize(recentProjects) - 1 + Local promoted.Project = ListAt(recentProjects, lastIndex) + + For i = lastIndex To 1 Step -1 + ListReplace(recentProjects, i, ListAt(recentProjects, i - 1)) + Next + + ListReplace(recentProjects, 0, promoted) +End Function + +Function RecentProjectsTrim(recentProjects.BBList, maxEntries%) + If recentProjects = Null Or maxEntries < 0 Then Return + + While ListSize(recentProjects) > maxEntries + ListRemove(recentProjects, ListSize(recentProjects) - 1) + Wend +End Function diff --git a/src/Project Manager.bb b/src/Project Manager.bb index ef097f5e..f00d36f2 100644 --- a/src/Project Manager.bb +++ b/src/Project Manager.bb @@ -14,6 +14,7 @@ Include "Modules\Graphics\UI\Components\TextComponent.bb" Include "Modules\Graphics\UI\Components\MenuItemComponent.bb" Include "Modules\Graphics\RCCEGraphics.bb" Include "Modules\Framework\Project\Project.bb" +Include "Modules\Project Manager\RecentProjects.bb" Type ProjectManager.RCCEApp Field window% @@ -121,7 +122,7 @@ Type ProjectManager.RCCEApp Local count = ListSize(self\recentProjectList) - 1 for i = 0 to count Local prj.Project = ListAt(self\recentProjectList, i) - if (prj\rootDir = dir) + if (NormalizeProjectRoot$(prj\rootDir) = NormalizeProjectRoot$(dir)) return prj end if next @@ -148,26 +149,17 @@ Type ProjectManager.RCCEApp return end if - if (NOT self\prj = null) - if(NOT self\recentProjectList = Null) - self\recentProjectList = CreateList() - end if - - if (ListSize(self\recentProjectList) > 0) - ListReplace(self\recentProjectList, 0, self\prj) - else - ListAdd(self\recentProjectList, self\prj) - end if + if self\recentProjectList = Null + self\recentProjectList = CreateList() end if + if (NOT self\prj = Null) Then RecentProjectsPromote(self\recentProjectList, self\prj) + Project::load(prj) self\prj = prj - if(NOT self\recentProjectList = Null) - if (ListFind(self\recentProjectList, self\prj) <> -1) - ListRemove(self\recentProjectList, ListFind(self\recentProjectList, self\prj)) - end if - end if + RecentProjectsRemoveByRootDir(self\recentProjectList, self\prj\rootDir) + RecentProjectsTrim(self\recentProjectList, 9) ProjectManager::saveRecentProjects(self) @@ -581,4 +573,4 @@ Repeat Until app\Quit = True FUI_Destroy() -End \ No newline at end of file +End diff --git a/src/Tests/Modules/RecentProjectsTest.bb b/src/Tests/Modules/RecentProjectsTest.bb new file mode 100644 index 00000000..2092082c --- /dev/null +++ b/src/Tests/Modules/RecentProjectsTest.bb @@ -0,0 +1,93 @@ +Strict +EnableGC + +Type Project + Field rootDir$ +End Type + +Include "Modules\Project Manager\RecentProjects.bb" + +Function CreateProject.Project(rootDir$) + Local prj.Project = New Project() + prj\rootDir = rootDir$ + Return prj +End Function + +Test testRecentProjectsPromotePreservesHistoryOrder() + Local recentProjects.BBList = CreateList() + Local current.Project = CreateProject("C:\Projects\Current\") + Local older.Project = CreateProject("C:\Projects\Older\") + Local oldest.Project = CreateProject("C:\Projects\Oldest\") + + ListAdd(recentProjects, older) + ListAdd(recentProjects, oldest) + + RecentProjectsPromote(recentProjects, current) + + Assert(ListSize(recentProjects) = 3) + Local firstProject.Project = ListAt(recentProjects, 0) + Local secondProject.Project = ListAt(recentProjects, 1) + Local thirdProject.Project = ListAt(recentProjects, 2) + Assert(firstProject\rootDir = current\rootDir) + Assert(secondProject\rootDir = older\rootDir) + Assert(thirdProject\rootDir = oldest\rootDir) + + FreeList(recentProjects) + Delete Each Project +End Test + +Test testRecentProjectsPromoteDeduplicatesNormalizedPaths() + Local recentProjects.BBList = CreateList() + Local remembered.Project = CreateProject("C:\Projects\Current") + Local duplicate.Project = CreateProject("c:/projects/current/") + Local other.Project = CreateProject("C:\Projects\Other") + + ListAdd(recentProjects, duplicate) + ListAdd(recentProjects, other) + + RecentProjectsPromote(recentProjects, remembered) + + Assert(ListSize(recentProjects) = 2) + Local firstProject.Project = ListAt(recentProjects, 0) + Local secondProject.Project = ListAt(recentProjects, 1) + Assert(firstProject\rootDir = remembered\rootDir) + Assert(secondProject\rootDir = other\rootDir) + + FreeList(recentProjects) + Delete Each Project +End Test + +Test testRecentProjectsRemoveByRootDirUsesNormalizedPaths() + Local recentProjects.BBList = CreateList() + + ListAdd(recentProjects, CreateProject("C:\Projects\One")) + ListAdd(recentProjects, CreateProject("C:\Projects\Two\")) + + RecentProjectsRemoveByRootDir(recentProjects, "c:/projects/two") + + Assert(ListSize(recentProjects) = 1) + Local firstProject.Project = ListAt(recentProjects, 0) + Assert(firstProject\rootDir = "C:\Projects\One") + + FreeList(recentProjects) + Delete Each Project +End Test + +Test testRecentProjectsTrimMatchesSavedHistoryLimit() + Local recentProjects.BBList = CreateList() + + For i = 0 To 11 + ListAdd(recentProjects, CreateProject("C:\Projects\" + Str$(i))) + Next + + RecentProjectsTrim(recentProjects, 9) + + Assert(ListSize(recentProjects) = 9) + Local firstProject.Project = ListAt(recentProjects, 0) + Local ninth.Project = ListAt(recentProjects, 8) + Assert(firstProject\rootDir = "C:\Projects\0") + Assert(ninth\rootDir = "C:\Projects\8") + + FreeList(recentProjects) + Delete Each Project +End Test