Repository: penpot/penpot
File: frontend/src/app/main/data/workspace/libraries.cljs (ClojureScript)

Code before:
            variants-count (-> library :library-summary :components :variants-count)

            loaded-libraries (->> (dsh/lookup-libraries state)
                                  (remove (fn [[_ lib]]
                                            (or (nil? (:data lib))
                                                (empty? (:data lib)))))
                                  (map first)
                                  set)

            libraries (update-vals libraries
                                   (fn [library]
                                     (assoc library
                                            :library-file-ids
                                            (->> (str/split (:library-file-ids library) #",")
                                                 (remove empty?)
                                                 (mapv uuid/uuid)))))
            libraries-to-load (as-> (all-used-libraries libraries library-id) $
                                (remove loaded-libraries $)
                                (conj $ library-id))]
        (rx/concat
         (rx/merge
          (->> (rp/cmd! :link-file-to-library {:file-id file-id :library-id library-id})
               (rx/ignore))
          (->> libraries-to-load
               (rx/from)
               (rx/map #(load-library-file file-id %))))
         (rx/of (ptk/reify ::attach-library-finished))
         (when (pos? variants-count)
           (->> (rp/cmd! :get-library-usage {:file-id library-id})
                (rx/map (fn [library-usage]
                          (ptk/event ::ev/event {::ev/name "attach-library-variants"
                                                 :file-id file-id
                                                 :library-id library-id
                                                 :variants-count variants-count
                                                 :library-used-in (:used-in library-usage)}))))))))))

(defn unlink-file-from-library
  [file-id library-id]
  (ptk/reify ::detach-library
    ev/Event
    (-data [_]
      {::ev/name "detach-library"
       :file-id file-id
       :library-id library-id})

    ptk/UpdateEvent
    (update [_ state]
      (update state :files dissoc library-id))

    ptk/WatchEvent
    (watch [_ _ _]

Review comment (refactor):
I undertand the idea behind this code,  but i think we can solve this much early, directly returning necessary libraries and transitive libraries from backend.

We already have on backend a query (used for exportation but the same idea can be reused here also i think) on `app.binfile.common/get-libraries` which retrieves all the libraries including the recursive ones.

I think a more simpler approach can be make the link-file-to-library method return a proper list of libraries linked (internally using the already existing helper for obtain recursive libraries), the current one and the transitive, and then we just can proceed to fetch the new libraries and resolve them  in the same way it is done on workspace initialization. With this approach we remove all this complex resolution logic from frontend.

Code after:
               (rx/merge-map (fn [libraries-to-load]
                               (as-> libraries-to-load $
                                 (remove loaded-libraries $)
                                 (conj $ library-id)
                                 (map #(load-library-file file-id %) $))))))
         (rx/of (ptk/reify ::attach-library-finished))
         (when (pos? variants-count)
           (->> (rp/cmd! :get-library-usage {:file-id library-id})
                (rx/map (fn [library-usage]
                          (ptk/event ::ev/event {::ev/name "attach-library-variants"
                                                 :file-id file-id
                                                 :library-id library-id
                                                 :variants-count variants-count
                                                 :library-used-in (:used-in library-usage)}))))))))))

(defn unlink-file-from-library
  [file-id library-id]
  (ptk/reify ::detach-library
    ev/Event
    (-data [_]
      {::ev/name "detach-library"
       :file-id file-id
       :library-id library-id})

    ptk/UpdateEvent
    (update [_ state]
      (update state :files dissoc library-id))

    ptk/WatchEvent
    (watch [_ _ _]
      (let [params {:file-id file-id
                    :library-id library-id}]
        (->> (rp/cmd! :unlink-file-from-library params)
             (rx/ignore))))))