[OCaml] Mobile-friendly clone of cgit.
feat collapse single-subdirectory chains in files view
Inspired by cgit, directories that contain only a single subdirectory are now collapsed together (e.g. 'src/lib/views/' instead of requiring three separate clicks). The preload resolver concatenates directory names and follows the chain until hitting a directory with multiple entries or files, eliminating wasted traversal clicks.
lib/resolvers.ml
@@ -361,18 +361,31 @@
361
361
let rec preload_entry (entry : Entry.t) =
362
362
if entry.perm <> Entry.Dir then
363
363
Lwt_result.return { entry; children = None }
364
Removed:
else
365
Removed:
let* hash = hash_of_hex entry.hash in
366
Removed:
let* subtree =
367
Removed:
Lwt_result.bind (read_value repository hash) @@ function
368
Removed:
| Git.Value.Tree t -> Lwt_result.return (to_t t)
369
Removed:
| _ -> Lwt_result.return { entries = [] }
370
Removed:
in
371
Removed:
let count = List.length subtree.entries in
372
Removed:
if count >= 10 then Lwt_result.return { entry; children = Some [] }
373
Removed:
else
374
Removed:
let* children = preload_entries subtree.entries in
375
Removed:
Lwt_result.return { entry; children = Some children }
364
Added:
else collapse_single_subdirs entry.name entry.hash
365
Added:
and collapse_single_subdirs prefix hash_hex =
366
Added:
let* hash = hash_of_hex hash_hex in
367
Added:
let* subtree =
368
Added:
Lwt_result.bind (read_value repository hash) @@ function
369
Added:
| Git.Value.Tree t -> Lwt_result.return (to_t t)
370
Added:
| _ -> Lwt_result.return { entries = [] }
371
Added:
in
372
Added:
let entries = subtree.entries in
373
Added:
match entries with
374
Added:
| [ single ] when single.perm = Entry.Dir ->
375
Added:
(* Single subdir — collapse into parent name and recurse *)
376
Added:
let combined_name = prefix ^ "/" ^ single.name in
377
Added:
collapse_single_subdirs combined_name single.hash
378
Added:
| _ ->
379
Added:
let count = List.length entries in
380
Added:
let collapsed_entry =
381
Added:
{ Entry.hash = hash_hex; name = prefix; perm = Entry.Dir }
382
Added:
in
383
Added:
if count >= 10 then
384
Added:
Lwt_result.return { entry = collapsed_entry; children = Some [] }
385
Added:
else
386
Added:
let* children = preload_entries entries in
387
Added:
Lwt_result.return
388
Added:
{ entry = collapsed_entry; children = Some children }
376
389
and preload_entries entries =
377
390
let rec go acc = function
378
391
| [] -> Lwt_result.return (List.rev acc)