From 8b14de2610ef7cbbb42827231178b8915d73b2b5 Mon Sep 17 00:00:00 2001 From: Dream <42954461+eureka0928@users.noreply.github.com> Date: Tue, 14 Apr 2026 04:50:46 -0400 Subject: [PATCH] :sparkles: Sort asset subfolders alphabetically (#8952) Subgroups in asset libraries were rendered in hash-map order because update-in descends into plain maps instead of sorted ones. Add a recursive post-process that rebuilds every level as a sorted-map so subfolders are alphabetical at every nesting depth. Closes #2572 Signed-off-by: eureka928 --- CHANGES.md | 1 + .../ui/workspace/sidebar/assets/groups.cljs | 35 ++++++++++++------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index af5d0da55d..709b24a7cf 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -31,6 +31,7 @@ - Use page name for multi-export ZIP/PDF downloads (by @Dexterity104) [Github #8773](https://github.com/penpot/penpot/issues/8773) - Make links in comments clickable (by @eureka928) [Github #1602](https://github.com/penpot/penpot/issues/1602) - Add visibility toggle for strokes (by @eureka928) [Github #7438](https://github.com/penpot/penpot/issues/7438) +- Sort asset library subfolders alphabetically at every nesting level (by @eureka928) [Github #2572](https://github.com/penpot/penpot/issues/2572) ### :bug: Bugs fixed diff --git a/frontend/src/app/main/ui/workspace/sidebar/assets/groups.cljs b/frontend/src/app/main/ui/workspace/sidebar/assets/groups.cljs index 3bc5fe58f1..4a781fa48a 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/assets/groups.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/assets/groups.cljs @@ -86,6 +86,17 @@ :on-click on-context-menu :icon i/menu}]]]))) +(defn- sort-groups + "Recursively sort subgroup keys alphabetically at every nesting level." + [groups reverse-sort?] + (let [cmp (if reverse-sort? #(compare %2 %1) compare) + sort-tree (fn sort-tree [m] + (into (sorted-map-by cmp) + (map (fn [[k v]] + [k (if (map? v) (sort-tree v) v)])) + m))] + (sort-tree groups))) + (defn group-assets "Convert a list of assets in a nested structure like this: @@ -97,19 +108,17 @@ " [assets reverse-sort?] (when-not (empty? assets) - (reduce (fn [groups {:keys [path] :as asset}] - (let [path (cpn/split-path (or path ""))] - (update-in groups - (conj path "") - (fn [group] - (if group - (conj group asset) - [asset]))))) - (sorted-map-by (fn [key1 key2] - (if reverse-sort? - (compare key2 key1) - (compare key1 key2)))) - assets))) + (-> (reduce (fn [groups {:keys [path] :as asset}] + (let [path (cpn/split-path (or path ""))] + (update-in groups + (conj path "") + (fn [group] + (if group + (conj group asset) + [asset]))))) + {} + assets) + (sort-groups reverse-sort?)))) (def ^:private schema:group-form [:map {:title "GroupForm"}