@@ -135,48 +135,109 @@ function toggleFolder(folderPath) {
135135 const folderRow = document . querySelector ( `[data-path="${ folderPath } "]` ) ;
136136 if ( ! folderRow ) return ;
137137
138- const isCollapsed = folderRow . classList . contains ( "collapsed" ) ;
139- const collapseIcon = folderRow . querySelector ( ".collapse-icon" ) ;
138+ const currentState = folderStates . get ( folderPath ) || "collapsed" ;
139+ const newState = currentState === "collapsed" ? "expanded" : "collapsed" ;
140+ folderStates . set ( folderPath , newState ) ;
140141
141- if ( isCollapsed ) {
142- // Expand folder - show all children
142+ if ( newState === "expanded" ) {
143+ // Expand folder - show only direct children
143144 folderRow . classList . remove ( "collapsed" ) ;
144- if ( collapseIcon ) collapseIcon . innerHTML = '<i class="bi bi-folder"></i>' ;
145145
146- // Show all descendant rows
146+ // Show only direct children (one level down) and restore their states
147147 const allRows = document . querySelectorAll ( ".game-row" ) ;
148148 allRows . forEach ( ( row ) => {
149149 const rowPath = row . getAttribute ( "data-path" ) ;
150150 if ( rowPath && rowPath . startsWith ( folderPath + "/" ) ) {
151- row . style . display = "" ;
152- // If this child row is also a collapsed folder, don't show its children
153- const childFolderPath = rowPath ;
154- const childRow = document . querySelector (
155- `[data-path="${ childFolderPath } "]` ,
156- ) ;
157- if ( childRow && childRow . classList . contains ( "collapsed" ) ) {
158- // Hide this collapsed folder's children
159- hideChildrenOfFolder ( childFolderPath ) ;
151+ // Check if this is a direct child (not a grandchild)
152+ const relativePath = rowPath . substring ( folderPath . length + 1 ) ;
153+ if ( ! relativePath . includes ( "/" ) ) {
154+ // This is a direct child, show it
155+ row . style . display = "" ;
156+
157+ // If this is a folder, restore its individual state
158+ if ( row . classList . contains ( "intermediate-folder" ) ) {
159+ const childState = folderStates . get ( rowPath ) || "collapsed" ;
160+ if ( childState === "expanded" ) {
161+ // This child was expanded, so expand it and show its children
162+ row . classList . remove ( "collapsed" ) ;
163+ showChildrenOfFolder ( rowPath ) ;
164+ } else {
165+ // This child was collapsed, so collapse it and hide its children
166+ row . classList . add ( "collapsed" ) ;
167+ hideChildrenOfFolder ( rowPath ) ;
168+ }
169+ }
160170 }
161171 }
162172 } ) ;
163173 } else {
164174 // Collapse folder - hide all children
165175 folderRow . classList . add ( "collapsed" ) ;
166- if ( collapseIcon )
167- collapseIcon . innerHTML = '<i class="bi bi-folder-open"></i>' ;
168176
169177 hideChildrenOfFolder ( folderPath ) ;
170178 }
171179}
172180
173181function hideChildrenOfFolder ( folderPath ) {
174- // Hide all descendant rows of a folder
182+ // Hide all descendant rows of a folder, but respect their individual states
183+ const allRows = document . querySelectorAll ( ".game-row" ) ;
184+ allRows . forEach ( ( row ) => {
185+ const rowPath = row . getAttribute ( "data-path" ) ;
186+ if ( rowPath && rowPath . startsWith ( folderPath + "/" ) ) {
187+ // Check if this is a direct child or a descendant
188+ const relativePath = rowPath . substring ( folderPath . length + 1 ) ;
189+
190+ if ( ! relativePath . includes ( "/" ) ) {
191+ // This is a direct child - hide it
192+ row . style . display = "none" ;
193+ } else {
194+ // This is a grandchild or deeper - check if its parent is visible
195+ const parentPath = rowPath . substring ( 0 , rowPath . lastIndexOf ( "/" ) ) ;
196+ const parentRow = document . querySelector ( `[data-path="${ parentPath } "]` ) ;
197+
198+ if ( parentRow && parentRow . style . display === "none" ) {
199+ // Parent is hidden, so hide this child too
200+ row . style . display = "none" ;
201+ }
202+ // If parent is visible, don't change this child's visibility
203+ // (it will be handled by its own parent's state)
204+ }
205+ }
206+ } ) ;
207+ }
208+
209+ function showChildrenOfFolder ( folderPath ) {
210+ // Show all descendant rows of a folder, respecting their individual states
175211 const allRows = document . querySelectorAll ( ".game-row" ) ;
176212 allRows . forEach ( ( row ) => {
177213 const rowPath = row . getAttribute ( "data-path" ) ;
178214 if ( rowPath && rowPath . startsWith ( folderPath + "/" ) ) {
179- row . style . display = "none" ;
215+ // Check if this is a direct child or a descendant
216+ const relativePath = rowPath . substring ( folderPath . length + 1 ) ;
217+
218+ if ( ! relativePath . includes ( "/" ) ) {
219+ // This is a direct child - show it
220+ row . style . display = "" ;
221+ } else {
222+ // This is a grandchild or deeper - check if its parent is visible and expanded
223+ const parentPath = rowPath . substring ( 0 , rowPath . lastIndexOf ( "/" ) ) ;
224+ const parentRow = document . querySelector ( `[data-path="${ parentPath } "]` ) ;
225+
226+ if ( parentRow && parentRow . style . display !== "none" ) {
227+ // Parent is visible, check if it's expanded
228+ const parentState = folderStates . get ( parentPath ) || "collapsed" ;
229+ if ( parentState === "expanded" ) {
230+ // Parent is expanded, so show this child
231+ row . style . display = "" ;
232+ } else {
233+ // Parent is collapsed, so hide this child
234+ row . style . display = "none" ;
235+ }
236+ } else {
237+ // Parent is hidden, so hide this child too
238+ row . style . display = "none" ;
239+ }
240+ }
180241 }
181242 } ) ;
182243}
@@ -536,4 +597,30 @@ document.addEventListener("DOMContentLoaded", function () {
536597 console . log ( "Available keyboard shortcuts:" ) ;
537598 console . log ( " Shift + Click: Range select checkboxes" ) ;
538599 console . log ( " Escape: Close move dialog" ) ;
600+
601+ // Collapse all folders by default
602+ collapseAllFolders ( ) ;
539603} ) ;
604+
605+ // Track individual folder states
606+ const folderStates = new Map ( ) ;
607+
608+ function collapseAllFolders ( ) {
609+ // Find all intermediate folder rows and collapse them
610+ const folderRows = document . querySelectorAll ( ".intermediate-folder" ) ;
611+ folderRows . forEach ( ( folderRow ) => {
612+ const folderPath = folderRow . getAttribute ( "data-path" ) ;
613+ if ( folderPath ) {
614+ // Set initial state to collapsed
615+ folderStates . set ( folderPath , "collapsed" ) ;
616+
617+ // Collapse the folder
618+ folderRow . classList . add ( "collapsed" ) ;
619+
620+ // Hide all children of this folder
621+ hideChildrenOfFolder ( folderPath ) ;
622+ }
623+ } ) ;
624+
625+ console . log ( `Collapsed ${ folderRows . length } folders on startup` ) ;
626+ }
0 commit comments